[clang] [lldb] [llvm] [mlir] [clang] builtins for atomicrmw fminmax/_num (PR #187139)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 18 06:14:17 PDT 2026
Andrzej =?utf-8?q?Warzyński?= <andrzej.warzynski at arm.com>,Simon Pilgrim
<llvm-dev at redking.me.uk>,Lewis Crawford <lcrawford at nvidia.com>,Ramkumar
Ramachandra <artagnon at tenstorrent.com>,
Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>,Luke Hutton
<luke.hutton at arm.com>,Zhijie Wang <yesterda9 at gmail.com>,Emimendoza
<emiliomendozareyes at gmail.com>,Vlad Serebrennikov
<serebrennikov.vladislav at gmail.com>,Pengcheng Wang
<wangpengcheng.pp at bytedance.com>,Nikita Popov <npopov at redhat.com>,Lang Hames
<lhames at gmail.com>,Alexis Engelke <engelke at in.tum.de>,lonely eagle
<2020382038 at qq.com>,Lang Hames <lhames at gmail.com>,Florian Hahn
<flo at fhahn.com>,Folkert de Vries <folkert at folkertdev.nl>,Lang Hames
<lhames at gmail.com>,Nikita Popov <npopov at redhat.com>,Sander de Smalen
<sander.desmalen at arm.com>,Will Froom <willfroom at google.com>,google-llvm-bazel-bot
<google-bazel-bot at google.com>,Alexis Engelke <engelke at in.tum.de>,Jonathan
Thackray <jonathan.thackray at arm.com>,Zahira Ammarguellat
<zahira.ammarguellat at intel.com>,Dmitry Vasilyev <dvassiliev at accesssoftek.com>
=?utf-8?q?,?=Gonzalo Brito Gadeschi <gonzalob at nvidia.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/187139 at github.com>
https://github.com/gonzalobg updated https://github.com/llvm/llvm-project/pull/187139
>From 30a01f6e58d640de182f44d99335c4d6132e3d1e Mon Sep 17 00:00:00 2001
From: Gonzalo Brito Gadeschi <gonzalob at nvidia.com>
Date: Tue, 17 Mar 2026 15:24:47 -0700
Subject: [PATCH 01/33] [clang] builtins for atomicrmw fminmax/_num
---
clang/include/clang/Basic/Builtins.td | 72 +++++++++++++++++
clang/lib/AST/Expr.cpp | 16 ++++
clang/lib/CodeGen/CGAtomic.cpp | 77 ++++++++++++++++++-
clang/lib/Sema/SemaChecking.cpp | 16 ++++
.../AArch64/atomic-ops-float-check-minmax.c | 59 ++++++++++++++
clang/test/Sema/atomic-ops.c | 76 ++++++++++++++++++
6 files changed, 312 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index a1c99ccba7676..599a3f9dfee1c 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2139,6 +2139,30 @@ def AtomicMinFetch : AtomicBuiltin {
let Prototype = "void(...)";
}
+def AtomicFMinimumFetch : AtomicBuiltin {
+ let Spellings = ["__atomic_fminimum_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFMaximumFetch : AtomicBuiltin {
+ let Spellings = ["__atomic_fmaximum_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFMinimumNumFetch : AtomicBuiltin {
+ let Spellings = ["__atomic_fminimum_num_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFMaximumNumFetch : AtomicBuiltin {
+ let Spellings = ["__atomic_fmaximum_num_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def AtomicNandFetch : AtomicBuiltin {
let Spellings = ["__atomic_nand_fetch"];
let Attributes = [CustomTypeChecking];
@@ -2332,6 +2356,30 @@ def ScopedAtomicMaxFetch : AtomicBuiltin {
let Prototype = "void(...)";
}
+def ScopedAtomicFMinimumFetch : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fminimum_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFMaximumFetch : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fmaximum_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFMinimumNumFetch : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fminimum_num_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFMaximumNumFetch : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fmaximum_num_fetch"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def ScopedAtomicUInc : AtomicBuiltin {
let Spellings = ["__scoped_atomic_fetch_uinc"];
let Attributes = [CustomTypeChecking];
@@ -2436,6 +2484,30 @@ def AtomicFetchMin : AtomicBuiltin {
let Prototype = "void(...)";
}
+def AtomicFetchFMinimum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fminimum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFetchFMaximum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fmaximum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFetchFMinimumNum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fminimum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFetchFMaximumNum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fmaximum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def AtomicFetchUInc : AtomicBuiltin {
let Spellings = ["__atomic_fetch_uinc"];
let Attributes = [CustomTypeChecking];
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 185e887fb05c3..f05d4c6a495ac 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -5288,8 +5288,16 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__atomic_nand_fetch:
case AO__atomic_min_fetch:
case AO__atomic_max_fetch:
+ case AO__atomic_fminimum_fetch:
+ case AO__atomic_fmaximum_fetch:
+ case AO__atomic_fminimum_num_fetch:
+ case AO__atomic_fmaximum_num_fetch:
case AO__atomic_fetch_min:
case AO__atomic_fetch_max:
+ case AO__atomic_fetch_fminimum:
+ case AO__atomic_fetch_fmaximum:
+ case AO__atomic_fetch_fminimum_num:
+ case AO__atomic_fetch_fmaximum_num:
case AO__atomic_fetch_uinc:
case AO__atomic_fetch_udec:
return 3;
@@ -5311,8 +5319,16 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__scoped_atomic_nand_fetch:
case AO__scoped_atomic_min_fetch:
case AO__scoped_atomic_max_fetch:
+ case AO__scoped_atomic_fminimum_fetch:
+ case AO__scoped_atomic_fmaximum_fetch:
+ case AO__scoped_atomic_fminimum_num_fetch:
+ case AO__scoped_atomic_fmaximum_num_fetch:
case AO__scoped_atomic_fetch_min:
case AO__scoped_atomic_fetch_max:
+ case AO__scoped_atomic_fetch_fminimum:
+ case AO__scoped_atomic_fetch_fmaximum:
+ case AO__scoped_atomic_fetch_fminimum_num:
+ case AO__scoped_atomic_fetch_fmaximum_num:
case AO__scoped_atomic_exchange_n:
case AO__scoped_atomic_fetch_uinc:
case AO__scoped_atomic_fetch_udec:
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 859ab20bb6740..afd8ab91a62da 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -530,10 +530,27 @@ static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
const bool IsFP = OldVal->getType()->isFloatingPointTy();
if (IsFP) {
- llvm::Intrinsic::ID IID = (Op == AtomicExpr::AO__atomic_max_fetch ||
- Op == AtomicExpr::AO__scoped_atomic_max_fetch)
- ? llvm::Intrinsic::maxnum
- : llvm::Intrinsic::minnum;
+ llvm::Intrinsic::ID IID;
+ if (Op == AtomicExpr::AO__atomic_max_fetch ||
+ Op == AtomicExpr::AO__scoped_atomic_max_fetch)
+ IID = llvm::Intrinsic::maxnum;
+ else if (Op == AtomicExpr::AO__atomic_min_fetch ||
+ Op == AtomicExpr::AO__scoped_atomic_min_fetch)
+ IID = llvm::Intrinsic::minnum;
+ else if (Op == AtomicExpr::AO__atomic_fmaximum_fetch ||
+ Op == AtomicExpr::AO__scoped_atomic_fmaximum_fetch)
+ IID = llvm::Intrinsic::maximum;
+ else if (Op == AtomicExpr::AO__atomic_fminimum_fetch ||
+ Op == AtomicExpr::AO__scoped_atomic_fminimum_fetch)
+ IID = llvm::Intrinsic::minimum;
+ else if (Op == AtomicExpr::AO__atomic_fmaximum_num_fetch ||
+ Op == AtomicExpr::AO__scoped_atomic_fmaximum_num_fetch)
+ IID = llvm::Intrinsic::maximumnum;
+ else if (Op == AtomicExpr::AO__atomic_fminimum_num_fetch ||
+ Op == AtomicExpr::AO__scoped_atomic_fminimum_num_fetch)
+ IID = llvm::Intrinsic::minimumnum;
+ else
+ llvm_unreachable("Unexpected atomic FP min/max operation");
return Builder.CreateBinaryIntrinsic(IID, OldVal, RHS, llvm::FMFSource(),
"newval");
@@ -545,10 +562,18 @@ static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
llvm_unreachable("Unexpected min/max operation");
case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_max_fetch:
+ case AtomicExpr::AO__atomic_fmaximum_fetch:
+ case AtomicExpr::AO__scoped_atomic_fmaximum_fetch:
+ case AtomicExpr::AO__atomic_fmaximum_num_fetch:
+ case AtomicExpr::AO__scoped_atomic_fmaximum_num_fetch:
Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
break;
case AtomicExpr::AO__atomic_min_fetch:
case AtomicExpr::AO__scoped_atomic_min_fetch:
+ case AtomicExpr::AO__atomic_fminimum_fetch:
+ case AtomicExpr::AO__scoped_atomic_fminimum_fetch:
+ case AtomicExpr::AO__atomic_fminimum_num_fetch:
+ case AtomicExpr::AO__scoped_atomic_fminimum_num_fetch:
Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
break;
}
@@ -705,6 +730,28 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
: llvm::AtomicRMWInst::UMin);
break;
+ case AtomicExpr::AO__atomic_fminimum_fetch:
+ case AtomicExpr::AO__scoped_atomic_fminimum_fetch:
+ PostOpMinMax = true;
+ [[fallthrough]];
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ assert(E->getValueType()->isFloatingType() &&
+ "fminimum operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMinimum;
+ break;
+
+ case AtomicExpr::AO__atomic_fminimum_num_fetch:
+ case AtomicExpr::AO__scoped_atomic_fminimum_num_fetch:
+ PostOpMinMax = true;
+ [[fallthrough]];
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ assert(E->getValueType()->isFloatingType() &&
+ "fminimum_num operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMinimumNum;
+ break;
+
case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_max_fetch:
PostOpMinMax = true;
@@ -721,6 +768,28 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
: llvm::AtomicRMWInst::UMax);
break;
+ case AtomicExpr::AO__atomic_fmaximum_fetch:
+ case AtomicExpr::AO__scoped_atomic_fmaximum_fetch:
+ PostOpMinMax = true;
+ [[fallthrough]];
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ assert(E->getValueType()->isFloatingType() &&
+ "fmaximum operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMaximum;
+ break;
+
+ case AtomicExpr::AO__atomic_fmaximum_num_fetch:
+ case AtomicExpr::AO__scoped_atomic_fmaximum_num_fetch:
+ PostOpMinMax = true;
+ [[fallthrough]];
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
+ assert(E->getValueType()->isFloatingType() &&
+ "fmaximum_num operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMaximumNum;
+ break;
+
case AtomicExpr::AO__atomic_and_fetch:
case AtomicExpr::AO__scoped_atomic_and_fetch:
PostOp = llvm::Instruction::And;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 29add9d092e6b..b03ab1c64104c 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4705,10 +4705,26 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__atomic_fetch_min:
case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__atomic_min_fetch:
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__atomic_fminimum_fetch:
+ case AtomicExpr::AO__atomic_fmaximum_fetch:
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
+ case AtomicExpr::AO__atomic_fminimum_num_fetch:
+ case AtomicExpr::AO__atomic_fmaximum_num_fetch:
case AtomicExpr::AO__scoped_atomic_fetch_max:
case AtomicExpr::AO__scoped_atomic_fetch_min:
case AtomicExpr::AO__scoped_atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_min_fetch:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fminimum_fetch:
+ case AtomicExpr::AO__scoped_atomic_fmaximum_fetch:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
+ case AtomicExpr::AO__scoped_atomic_fminimum_num_fetch:
+ case AtomicExpr::AO__scoped_atomic_fmaximum_num_fetch:
case AtomicExpr::AO__c11_atomic_fetch_max:
case AtomicExpr::AO__c11_atomic_fetch_min:
case AtomicExpr::AO__opencl_atomic_fetch_max:
diff --git a/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c b/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c
index 4d9b29b789507..d525a6d86f1f1 100644
--- a/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c
+++ b/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c
@@ -115,3 +115,62 @@ void test_minmax_postop(float *f32, _Float16 *f16, __bf16 *bf16, double *f64) {
*f16 = __atomic_min_fetch(f16, 42.1, memory_order_release);
*bf16 = __atomic_min_fetch(bf16, 42.1, memory_order_release);
}
+
+// CHECK-LABEL: define dso_local void @test_fminimum_fmaximum_postop(
+// CHECK-SAME: ptr noundef [[F32:%.*]], ptr noundef [[F16:%.*]], ptr noundef [[BF16:%.*]], ptr noundef [[F64:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK: [[TMP0:%.*]] = load ptr, ptr [[F64_ADDR]], align 8
+// CHECK: store double 4.210000e+01, ptr [[DOTATOMICTMP]], align 8
+// CHECK: [[TMP1:%.*]] = load double, ptr [[DOTATOMICTMP]], align 8
+// CHECK: [[TMP2:%.*]] = atomicrmw fmaximum ptr [[TMP0]], double [[TMP1]] release, align 8
+// CHECK: [[NEWVAL:%.*]] = call double @llvm.maximum.f64(double [[TMP2]], double [[TMP1]])
+// CHECK: store double [[NEWVAL]], ptr [[ATOMIC_TEMP]], align 8
+// CHECK: [[TMP3:%.*]] = load double, ptr [[ATOMIC_TEMP]], align 8
+// CHECK: [[TMP4:%.*]] = load ptr, ptr [[F64_ADDR]], align 8
+// CHECK: store double [[TMP3]], ptr [[TMP4]], align 8
+void test_fminimum_fmaximum_postop(float *f32, _Float16 *f16, __bf16 *bf16, double *f64) {
+ *f64 = __atomic_fmaximum_fetch(f64, 42.1, memory_order_release);
+ *f32 = __atomic_fmaximum_fetch(f32, 42.1, memory_order_release);
+ *f16 = __atomic_fmaximum_fetch(f16, 42.1, memory_order_release);
+ *bf16 = __atomic_fmaximum_fetch(bf16, 42.1, memory_order_release);
+ *f64 = __atomic_fminimum_fetch(f64, 42.1, memory_order_release);
+ *f32 = __atomic_fminimum_fetch(f32, 42.1, memory_order_release);
+ *f16 = __atomic_fminimum_fetch(f16, 42.1, memory_order_release);
+ *bf16 = __atomic_fminimum_fetch(bf16, 42.1, memory_order_release);
+}
+
+// CHECK-LABEL: define dso_local void @test_fminimumnum_fmaximumnum_postop(
+// CHECK-SAME: ptr noundef [[F32:%.*]], ptr noundef [[F16:%.*]], ptr noundef [[BF16:%.*]], ptr noundef [[F64:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK: [[TMP0:%.*]] = load ptr, ptr [[F64_ADDR]], align 8
+// CHECK: store double 4.210000e+01, ptr [[DOTATOMICTMP]], align 8
+// CHECK: [[TMP1:%.*]] = load double, ptr [[DOTATOMICTMP]], align 8
+// CHECK: [[TMP2:%.*]] = atomicrmw fmaximumnum ptr [[TMP0]], double [[TMP1]] release, align 8
+// CHECK: [[NEWVAL:%.*]] = call double @llvm.maximumnum.f64(double [[TMP2]], double [[TMP1]])
+// CHECK: store double [[NEWVAL]], ptr [[ATOMIC_TEMP]], align 8
+// CHECK: [[TMP3:%.*]] = load double, ptr [[ATOMIC_TEMP]], align 8
+// CHECK: [[TMP4:%.*]] = load ptr, ptr [[F64_ADDR]], align 8
+// CHECK: store double [[TMP3]], ptr [[TMP4]], align 8
+void test_fminimumnum_fmaximumnum_postop(float *f32, _Float16 *f16, __bf16 *bf16, double *f64) {
+ *f64 = __atomic_fmaximum_num_fetch(f64, 42.1, memory_order_release);
+ *f32 = __atomic_fmaximum_num_fetch(f32, 42.1, memory_order_release);
+ *f16 = __atomic_fmaximum_num_fetch(f16, 42.1, memory_order_release);
+ *bf16 = __atomic_fmaximum_num_fetch(bf16, 42.1, memory_order_release);
+ *f64 = __atomic_fminimum_num_fetch(f64, 42.1, memory_order_release);
+ *f32 = __atomic_fminimum_num_fetch(f32, 42.1, memory_order_release);
+ *f16 = __atomic_fminimum_num_fetch(f16, 42.1, memory_order_release);
+ *bf16 = __atomic_fminimum_num_fetch(bf16, 42.1, memory_order_release);
+}
+
+// CHECK-LABEL: define dso_local void @test_fetch_variants(
+// CHECK-SAME: ptr noundef [[F64:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK: [[TMP0:%.*]] = atomicrmw fminimum ptr {{%.*}}, double {{%.*}} release, align 8
+// CHECK: [[TMP1:%.*]] = atomicrmw fmaximum ptr {{%.*}}, double {{%.*}} release, align 8
+// CHECK: [[TMP2:%.*]] = atomicrmw fminimumnum ptr {{%.*}}, double {{%.*}} release, align 8
+// CHECK: [[TMP3:%.*]] = atomicrmw fmaximumnum ptr {{%.*}}, double {{%.*}} release, align 8
+void test_fetch_variants(double *f64) {
+ double old1 = __atomic_fetch_fminimum(f64, 42.1, memory_order_release);
+ double old2 = __atomic_fetch_fmaximum(f64, 42.1, memory_order_release);
+ double old3 = __atomic_fetch_fminimum_num(f64, 42.1, memory_order_release);
+ double old4 = __atomic_fetch_fmaximum_num(f64, 42.1, memory_order_release);
+}
diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c
index 3318e369f3e0d..29c3cc7f22bcf 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -252,6 +252,18 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__atomic_fetch_max(D, 3, memory_order_seq_cst);
__atomic_fetch_max(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or supported floating point type}}
__atomic_fetch_max(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}}
+ __atomic_fetch_fminimum(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fminimum(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or supported floating point type}}
+ __atomic_fetch_fmaximum(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}}
+ __atomic_fetch_fminimum_num(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fminimum_num(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum_num(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum_num(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum_num(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or supported floating point type}}
+ __atomic_fetch_fmaximum_num(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}}
__atomic_fetch_uinc(F, 1, memory_order_seq_cst); // expected-error {{address argument to atomic operation must be a pointer to integer}}
__atomic_fetch_udec(F, 1, memory_order_seq_cst); // expected-error {{address argument to atomic operation must be a pointer to integer}}
@@ -601,6 +613,20 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_fetch_min(p, val, memory_order_acq_rel);
(void)__atomic_fetch_min(p, val, memory_order_seq_cst);
+ (void)__atomic_fetch_fminimum(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_fminimum(p, val, memory_order_acquire);
+ (void)__atomic_fetch_fminimum(p, val, memory_order_consume);
+ (void)__atomic_fetch_fminimum(p, val, memory_order_release);
+ (void)__atomic_fetch_fminimum(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_fminimum(p, val, memory_order_seq_cst);
+
+ (void)__atomic_fetch_fminimum_num(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_fminimum_num(p, val, memory_order_acquire);
+ (void)__atomic_fetch_fminimum_num(p, val, memory_order_consume);
+ (void)__atomic_fetch_fminimum_num(p, val, memory_order_release);
+ (void)__atomic_fetch_fminimum_num(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_fminimum_num(p, val, memory_order_seq_cst);
+
(void)__atomic_fetch_uinc(p, val, memory_order_relaxed);
(void)__atomic_fetch_uinc(p, val, memory_order_acquire);
(void)__atomic_fetch_uinc(p, val, memory_order_consume);
@@ -622,6 +648,20 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_fetch_max(p, val, memory_order_acq_rel);
(void)__atomic_fetch_max(p, val, memory_order_seq_cst);
+ (void)__atomic_fetch_fmaximum(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_fmaximum(p, val, memory_order_acquire);
+ (void)__atomic_fetch_fmaximum(p, val, memory_order_consume);
+ (void)__atomic_fetch_fmaximum(p, val, memory_order_release);
+ (void)__atomic_fetch_fmaximum(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_fmaximum(p, val, memory_order_seq_cst);
+
+ (void)__atomic_fetch_fmaximum_num(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_fmaximum_num(p, val, memory_order_acquire);
+ (void)__atomic_fetch_fmaximum_num(p, val, memory_order_consume);
+ (void)__atomic_fetch_fmaximum_num(p, val, memory_order_release);
+ (void)__atomic_fetch_fmaximum_num(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_fmaximum_num(p, val, memory_order_seq_cst);
+
(void)__atomic_and_fetch(p, val, memory_order_relaxed);
(void)__atomic_and_fetch(p, val, memory_order_acquire);
(void)__atomic_and_fetch(p, val, memory_order_consume);
@@ -664,6 +704,34 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_min_fetch(p, val, memory_order_acq_rel);
(void)__atomic_min_fetch(p, val, memory_order_seq_cst);
+ (void)__atomic_fmaximum_fetch(p, val, memory_order_relaxed);
+ (void)__atomic_fmaximum_fetch(p, val, memory_order_acquire);
+ (void)__atomic_fmaximum_fetch(p, val, memory_order_consume);
+ (void)__atomic_fmaximum_fetch(p, val, memory_order_release);
+ (void)__atomic_fmaximum_fetch(p, val, memory_order_acq_rel);
+ (void)__atomic_fmaximum_fetch(p, val, memory_order_seq_cst);
+
+ (void)__atomic_fminimum_fetch(p, val, memory_order_relaxed);
+ (void)__atomic_fminimum_fetch(p, val, memory_order_acquire);
+ (void)__atomic_fminimum_fetch(p, val, memory_order_consume);
+ (void)__atomic_fminimum_fetch(p, val, memory_order_release);
+ (void)__atomic_fminimum_fetch(p, val, memory_order_acq_rel);
+ (void)__atomic_fminimum_fetch(p, val, memory_order_seq_cst);
+
+ (void)__atomic_fmaximum_num_fetch(p, val, memory_order_relaxed);
+ (void)__atomic_fmaximum_num_fetch(p, val, memory_order_acquire);
+ (void)__atomic_fmaximum_num_fetch(p, val, memory_order_consume);
+ (void)__atomic_fmaximum_num_fetch(p, val, memory_order_release);
+ (void)__atomic_fmaximum_num_fetch(p, val, memory_order_acq_rel);
+ (void)__atomic_fmaximum_num_fetch(p, val, memory_order_seq_cst);
+
+ (void)__atomic_fminimum_num_fetch(p, val, memory_order_relaxed);
+ (void)__atomic_fminimum_num_fetch(p, val, memory_order_acquire);
+ (void)__atomic_fminimum_num_fetch(p, val, memory_order_consume);
+ (void)__atomic_fminimum_num_fetch(p, val, memory_order_release);
+ (void)__atomic_fminimum_num_fetch(p, val, memory_order_acq_rel);
+ (void)__atomic_fminimum_num_fetch(p, val, memory_order_seq_cst);
+
(void)__atomic_exchange_n(p, val, memory_order_relaxed);
(void)__atomic_exchange_n(p, val, memory_order_acquire);
(void)__atomic_exchange_n(p, val, memory_order_consume);
@@ -851,6 +919,14 @@ void nullPointerWarning(void) {
(void)__atomic_fetch_min((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
(void)__atomic_fetch_max((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
(void)__atomic_fetch_max((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum_num((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum_num((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum_num((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum_num((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
// These don't warn: the "desired" parameter is passed by value. Even for
// atomic pointers the "desired" result can be NULL.
>From e7a7e49a11b36340f6f1428689031491d8bf7f3d Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 18 Mar 2026 16:42:21 +0800
Subject: [PATCH 02/33] [X86] Remove extranous I in comment. NFC (#187209)
Seems to have slipped in in c63d2953a08b9
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index d9f253c2837f8..c69666e9f4522 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -1,4 +1,3 @@
-// I
//===-- X86ISelLowering.cpp - X86 DAG Lowering Implementation -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>From f5440217893d24178b949fbd5837b56e9538720a Mon Sep 17 00:00:00 2001
From: Joshua Rodriguez <josh.rodriguez at arm.com>
Date: Wed, 18 Mar 2026 08:51:16 +0000
Subject: [PATCH 03/33] [AArch64][GlobalISel] Fix uqadd/sub with scalar
operands (#186999)
Previously, neon uqadd/uqsub would not lower when given s32/s64
operands, as GlobalISel would wrongly try to put the operands on
general-purpose register banks. Changing this in RegBankSelection allows
the intrinsics to lower just like their signed versions.
---
llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp | 2 ++
llvm/test/CodeGen/AArch64/arm64-int-neon.ll | 4 ----
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index 03f714cddec83..b7ece4603fe19 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -619,7 +619,9 @@ static bool isFPIntrinsic(const MachineRegisterInfo &MRI,
case Intrinsic::aarch64_neon_sqrdmlah:
case Intrinsic::aarch64_neon_sqrdmlsh:
case Intrinsic::aarch64_neon_sqrdmulh:
+ case Intrinsic::aarch64_neon_uqadd:
case Intrinsic::aarch64_neon_sqadd:
+ case Intrinsic::aarch64_neon_uqsub:
case Intrinsic::aarch64_neon_sqsub:
case Intrinsic::aarch64_neon_srshl:
case Intrinsic::aarch64_neon_urshl:
diff --git a/llvm/test/CodeGen/AArch64/arm64-int-neon.ll b/llvm/test/CodeGen/AArch64/arm64-int-neon.ll
index 309a17798b13c..1352aeef08b86 100644
--- a/llvm/test/CodeGen/AArch64/arm64-int-neon.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-int-neon.ll
@@ -6,10 +6,6 @@
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_suqadd_s64
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_usqadd_s32
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_usqadd_s64
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_uqadd_s32
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_uqadd_s64
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_uqsub_s32
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_uqsub_s64
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_sqdmulls_scalar
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_sqdmulh_scalar
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for test_sqabs_s32
>From 2caf4f011334d9f4b68ce80e2fa06aa1762f4a4b Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 18 Mar 2026 08:54:23 +0000
Subject: [PATCH 04/33] [VPlan] Use auto return in VPlanPatternMatch (NFC)
(#187210)
---
.../Transforms/Vectorize/VPlanPatternMatch.h | 43 +++++--------------
1 file changed, 10 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index 1205f04fb5c29..f52b9ba8b1c5b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -796,16 +796,7 @@ m_SpecificCmp(CmpPredicate MatchPred, const Op0_t &Op0, const Op1_t &Op1) {
}
template <typename Op0_t, typename Op1_t>
-using GEPLikeRecipe_match = match_combine_or<
- Recipe_match<std::tuple<Op0_t, Op1_t>, Instruction::GetElementPtr,
- /*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe>,
- match_combine_or<
- VPInstruction_match<VPInstruction::PtrAdd, Op0_t, Op1_t>,
- VPInstruction_match<VPInstruction::WidePtrAdd, Op0_t, Op1_t>>>;
-
-template <typename Op0_t, typename Op1_t>
-inline GEPLikeRecipe_match<Op0_t, Op1_t> m_GetElementPtr(const Op0_t &Op0,
- const Op1_t &Op1) {
+inline auto m_GetElementPtr(const Op0_t &Op0, const Op1_t &Op1) {
return m_CombineOr(
Recipe_match<std::tuple<Op0_t, Op1_t>, Instruction::GetElementPtr,
/*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe>(
@@ -823,11 +814,7 @@ m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
{Op0, Op1, Op2});
}
-template <typename Op0_t>
-inline match_combine_or<VPInstruction_match<VPInstruction::Not, Op0_t>,
- AllRecipe_commutative_match<
- Instruction::Xor, int_pred_ty<is_all_ones>, Op0_t>>
-m_Not(const Op0_t &Op0) {
+template <typename Op0_t> inline auto m_Not(const Op0_t &Op0) {
return m_CombineOr(m_VPInstruction<VPInstruction::Not>(Op0),
m_c_Binary<Instruction::Xor>(m_AllOnes(), Op0));
}
@@ -838,10 +825,7 @@ inline auto m_c_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
}
template <typename Op0_t, typename Op1_t>
-inline match_combine_or<
- VPInstruction_match<VPInstruction::LogicalAnd, Op0_t, Op1_t>,
- AllRecipe_match<Instruction::Select, Op0_t, Op1_t, specific_intval<1>>>
-m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
+inline auto m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
return m_CombineOr(
m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1),
m_Select(Op0, Op1, m_False()));
@@ -869,23 +853,16 @@ inline auto m_c_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
inline auto m_CanonicalIV() { return class_match<VPCanonicalIVPHIRecipe>(); }
template <typename Op0_t, typename Op1_t, typename Op2_t>
-using VPScalarIVSteps_match = Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0,
- false, VPScalarIVStepsRecipe>;
-
-template <typename Op0_t, typename Op1_t, typename Op2_t>
-inline VPScalarIVSteps_match<Op0_t, Op1_t, Op2_t>
-m_ScalarIVSteps(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
- return VPScalarIVSteps_match<Op0_t, Op1_t, Op2_t>({Op0, Op1, Op2});
+inline auto m_ScalarIVSteps(const Op0_t &Op0, const Op1_t &Op1,
+ const Op2_t &Op2) {
+ return Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0, false,
+ VPScalarIVStepsRecipe>({Op0, Op1, Op2});
}
template <typename Op0_t, typename Op1_t, typename Op2_t>
-using VPDerivedIV_match =
- Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0, false, VPDerivedIVRecipe>;
-
-template <typename Op0_t, typename Op1_t, typename Op2_t>
-inline VPDerivedIV_match<Op0_t, Op1_t, Op2_t>
-m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
- return VPDerivedIV_match<Op0_t, Op1_t, Op2_t>({Op0, Op1, Op2});
+inline auto m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
+ return Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0, false,
+ VPDerivedIVRecipe>({Op0, Op1, Op2});
}
template <typename Addr_t, typename Mask_t> struct Load_match {
>From 53ad284f1cc3b270854fbb5003940b3461c2b0d1 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Wed, 18 Mar 2026 17:02:24 +0800
Subject: [PATCH 05/33] [NFCI] [Serialization] Deduplicate DeclID properly
(#187212)
In the original code, the operation to iterate Found is meaningless, as
it is guarded by Found.empty(). So this is always a noop for 10 years.
According to the context, I believe the intention is to avoid duplicated
DeclID to be in Data. So changing iterating Found to Data.
Just found by looking around the code.
This is not strictly NFC but NFC intentionally. I will be surprised if
this breaks anything.
---
clang/lib/Serialization/ASTReaderInternals.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Serialization/ASTReaderInternals.h b/clang/lib/Serialization/ASTReaderInternals.h
index 4a7794889b039..a132d01a21128 100644
--- a/clang/lib/Serialization/ASTReaderInternals.h
+++ b/clang/lib/Serialization/ASTReaderInternals.h
@@ -61,7 +61,7 @@ class ASTDeclContextNameLookupTraitBase {
// Just use a linear scan unless we have more than a few IDs.
if (Found.empty() && !Data.empty()) {
if (Data.size() <= 4) {
- for (auto I : Found)
+ for (auto I : Data)
if (I == ID)
return;
Data.push_back(ID);
@@ -183,7 +183,7 @@ class LazySpecializationInfoLookupTrait {
// Just use a linear scan unless we have more than a few IDs.
if (Found.empty() && !Data.empty()) {
if (Data.size() <= 4) {
- for (auto I : Found)
+ for (auto I : Data)
if (I == Info)
return;
Data.push_back(Info);
>From f25d4e5a9589ce07ee5e605b8bed5b8da8fbdae8 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 18 Mar 2026 17:14:29 +0800
Subject: [PATCH 06/33] [llvm][utils] Give git-llvm-push u+x permissions
(#187211)
There's a hashbang at the top of the script so I presume the intention
is that it can be executed directly, but it seems to be lacking
executable permissions. This sets the user executable bit so running
./llvm/utils/git-llvm-push works
---
llvm/utils/git-llvm-push | 0
1 file changed, 0 insertions(+), 0 deletions(-)
mode change 100644 => 100755 llvm/utils/git-llvm-push
diff --git a/llvm/utils/git-llvm-push b/llvm/utils/git-llvm-push
old mode 100644
new mode 100755
>From 38e00bab9ed618e8706a73ce1aa374b445740728 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= <andrzej.warzynski at arm.com>
Date: Wed, 18 Mar 2026 09:23:17 +0000
Subject: [PATCH 07/33] [mlir][vector] Extend vector.gather e2e test (#187071)
Extend the vector.gather e2e test to cover both available lowering
paths:
* Direct lowering to LLVM (via -test-lower-to-llvm)
* Lowering via vector.load (via -test-vector-gather-lowering)
This is a follow-up to https://github.com/llvm/llvm-project/pull/184706,
which updated a pattern used by -test-vector-gather-lowering.
The test is extended to operate on 2D memrefs so that the changes
in https://github.com/llvm/llvm-project/pull/184706 are meaningfully
exercised.
---
.../Dialect/Vector/CPU/gather.mlir | 81 +++++++++++--------
1 file changed, 49 insertions(+), 32 deletions(-)
diff --git a/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir b/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir
index ab2e713e83a6c..daf641d03eb75 100644
--- a/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir
+++ b/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir
@@ -1,13 +1,28 @@
-// RUN: mlir-opt %s -test-lower-to-llvm | \
-// RUN: mlir-runner -e entry -entry-point-result=void \
-// RUN: -shared-libs=%mlir_c_runner_utils | \
-// RUN: FileCheck %s
+// DEFINE: %{entry_point} = main
+// DEFINE: %{run} = mlir-runner -e entry -entry-point-result=void \
+// DEFINE: -shared-libs=%native_mlir_runner_utils,%native_mlir_c_runner_utils
-func.func @gather8(%base: memref<?xf32>, %indices: vector<8xi32>,
+/// TEST 1. Verify default compilation (direct lowering of `vector.gather` to LLVM)
+// DEFINE: %{compile} = mlir-opt %s -test-lower-to-llvm
+// RUN: %{compile} | %{run} | FileCheck %s
+
+/// TEST 2. Verify compilation via `test-vector-gather-lowering` (`vector.gather`
+/// lowerd to LLVM via `vector.load`)
+// REDEFINE: %{compile} = mlir-opt %s --test-vector-gather-lowering | mlir-opt -test-lower-to-llvm
+// RUN: %{compile} | %{run} | FileCheck %s
+
+/// TEST 3. Verify that `test-vector-gather-lowering` will indeed produce
+/// `vector.load`
+// REDEFINE: %{compile} = mlir-opt %s --test-vector-gather-lowering
+// RUN: %{compile} | FileCheck %s -check-prefix CHECK-IR
+
+func.func @gather8(%base: memref<?x?xf32>, %indices: vector<8xi32>,
%mask: vector<8xi1>, %pass_thru: vector<8xf32>) -> vector<8xf32> {
%c0 = arith.constant 0: index
- %g = vector.gather %base[%c0][%indices], %mask, %pass_thru
- : memref<?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32> into vector<8xf32>
+ /// Verify that the lowering via vector.load does indeed generate vector.load
+ // CHECK-IR-COUNT-4: vector.load
+ %g = vector.gather %base[%c0, %c0][%indices], %mask, %pass_thru
+ : memref<?x?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32> into vector<8xf32>
return %g : vector<8xf32>
}
@@ -16,29 +31,36 @@ func.func @entry() {
%c0 = arith.constant 0: index
%c1 = arith.constant 1: index
%c10 = arith.constant 10: index
- %A = memref.alloc(%c10) : memref<?xf32>
+ %c5 = arith.constant 5: index
+ %A = memref.alloc(%c10, %c5) : memref<?x?xf32>
scf.for %i = %c0 to %c10 step %c1 {
- %i32 = arith.index_cast %i : index to i32
- %fi = arith.sitofp %i32 : i32 to f32
- memref.store %fi, %A[%i] : memref<?xf32>
+ scf.for %j = %c0 to %c5 step %c1 {
+ %off = arith.muli %i, %c10 : index
+ %val_index = arith.addi %j, %off : index
+ %val_i32 = arith.index_cast %val_index : index to i32
+ %val = arith.sitofp %val_i32 : i32 to f32
+ memref.store %val, %A[%i, %j] : memref<?x?xf32>
+ }
}
+ %A_cast = memref.cast %A : memref<?x?xf32> to memref<*xf32>
+ call @printMemrefF32(%A_cast) : (memref<*xf32>) -> ()
// Set up idx vector.
%i0 = arith.constant 0: i32
- %i1 = arith.constant 1: i32
- %i2 = arith.constant 2: i32
- %i3 = arith.constant 3: i32
- %i4 = arith.constant 4: i32
- %i5 = arith.constant 5: i32
- %i6 = arith.constant 6: i32
- %i9 = arith.constant 9: i32
%0 = vector.broadcast %i0 : i32 to vector<8xi32>
+ %i6 = arith.constant 16: i32
%1 = vector.insert %i6, %0[1] : i32 into vector<8xi32>
+ %i1 = arith.constant 11: i32
%2 = vector.insert %i1, %1[2] : i32 into vector<8xi32>
+ %i3 = arith.constant 33: i32
%3 = vector.insert %i3, %2[3] : i32 into vector<8xi32>
+ %i5 = arith.constant 5: i32
%4 = vector.insert %i5, %3[4] : i32 into vector<8xi32>
+ %i4 = arith.constant 44: i32
%5 = vector.insert %i4, %4[5] : i32 into vector<8xi32>
+ %i9 = arith.constant 19: i32
%6 = vector.insert %i9, %5[6] : i32 into vector<8xi32>
+ %i2 = arith.constant 22: i32
%idx = vector.insert %i2, %6[7] : i32 into vector<8xi32>
// Set up pass thru vector.
@@ -57,35 +79,30 @@ func.func @entry() {
//
%g1 = call @gather8(%A, %idx, %all, %pass)
- : (memref<?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
+ : (memref<?x?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
-> (vector<8xf32>)
vector.print %g1 : vector<8xf32>
- // CHECK: ( 0, 6, 1, 3, 5, 4, 9, 2 )
+ // CHECK: ( 0, 31, 21, 63, 10, 84, 34, 42 )
%g2 = call @gather8(%A, %idx, %none, %pass)
- : (memref<?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
+ : (memref<?x?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
-> (vector<8xf32>)
vector.print %g2 : vector<8xf32>
// CHECK: ( -7, -7, -7, -7, -7, -7, -7, -7 )
%g3 = call @gather8(%A, %idx, %some, %pass)
- : (memref<?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
+ : (memref<?x?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
-> (vector<8xf32>)
vector.print %g3 : vector<8xf32>
- // CHECK: ( 0, 6, 1, 3, -7, -7, -7, -7 )
+ // CHECK: ( 0, 31, 21, 63, -7, -7, -7, -7 )
%g4 = call @gather8(%A, %idx, %more, %pass)
- : (memref<?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
+ : (memref<?x?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
-> (vector<8xf32>)
vector.print %g4 : vector<8xf32>
- // CHECK: ( 0, 6, 1, 3, -7, -7, -7, 2 )
-
- %g5 = call @gather8(%A, %idx, %all, %pass)
- : (memref<?xf32>, vector<8xi32>, vector<8xi1>, vector<8xf32>)
- -> (vector<8xf32>)
- vector.print %g5 : vector<8xf32>
- // CHECK: ( 0, 6, 1, 3, 5, 4, 9, 2 )
+ // CHECK: ( 0, 31, 21, 63, -7, -7, -7, 42 )
- memref.dealloc %A : memref<?xf32>
+ memref.dealloc %A : memref<?x?xf32>
return
}
+func.func private @printMemrefF32(%ptr : memref<*xf32>)
>From 736a472e2e473c87899483b46e95fab63a10ffc5 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Wed, 18 Mar 2026 09:30:39 +0000
Subject: [PATCH 08/33] [X86] Improve handling of i512 SRA(MSB,Amt) "highbits"
mask creation (#187141)
This can be folded from ((1 << 511) >>s Amt) -> (-1 << (511-Amt)) to make use of the existing optimal codegen
Alive2: https://alive2.llvm.org/ce/z/9UMQkm
Last i512 pattern described in #132601
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 10 +++
llvm/test/CodeGen/X86/shift-i512.ll | 89 +++++++++++--------------
2 files changed, 48 insertions(+), 51 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c69666e9f4522..a3c3e73864e6e 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -34524,6 +34524,16 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(DAG.getBitcast(VT, Res));
return;
}
+ // SRA(MSB,Amt) --> SHL(-1,(BW-1)-Amt)
+ if (Opc == ISD::SRA && SrcVal.isSignMask()) {
+ Amt = DAG.getZExtOrTrunc(Amt, dl, MVT::i32);
+ Amt = DAG.getNode(ISD::SUB, dl, MVT::i32,
+ DAG.getConstant(BW - 1, dl, MVT::i32), Amt);
+ SDValue Res =
+ DAG.getNode(ISD::SHL, dl, VT, DAG.getAllOnesConstant(dl, VT), Amt);
+ Results.push_back(DAG.getBitcast(VT, Res));
+ return;
+ }
}
// Use EXPAND/COMPRESS to shuffle the i64 elements left/right with the
diff --git a/llvm/test/CodeGen/X86/shift-i512.ll b/llvm/test/CodeGen/X86/shift-i512.ll
index bd73de7d50f1b..4e43ea1438b4f 100644
--- a/llvm/test/CodeGen/X86/shift-i512.ll
+++ b/llvm/test/CodeGen/X86/shift-i512.ll
@@ -2055,70 +2055,57 @@ define i512 @ashr_signbit_i512(i512 %a0) nounwind {
;
; AVX512F-LABEL: ashr_signbit_i512:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: movl %esi, %eax
-; AVX512F-NEXT: shrl $6, %esi
-; AVX512F-NEXT: movl $-1, %ecx
-; AVX512F-NEXT: shlxl %esi, %ecx, %ecx
-; AVX512F-NEXT: kmovw %ecx, %k1
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm0 = -1
-; AVX512F-NEXT: vmovdqa64 {{.*#+}} zmm1 = [0,0,0,0,0,0,0,9223372036854775808]
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm2 = -1
-; AVX512F-NEXT: vpcompressq %zmm1, %zmm2 {%k1}
-; AVX512F-NEXT: vmovq %rax, %xmm1
-; AVX512F-NEXT: vpbroadcastq %xmm1, %xmm1
-; AVX512F-NEXT: vpbroadcastq {{.*#+}} xmm3 = [63,63]
-; AVX512F-NEXT: vpand %xmm3, %xmm1, %xmm4
-; AVX512F-NEXT: vpsrlq %xmm4, %zmm2, %zmm4
-; AVX512F-NEXT: vpandn %xmm3, %xmm1, %xmm1
-; AVX512F-NEXT: valignq {{.*#+}} zmm0 = zmm2[1,2,3,4,5,6,7],zmm0[0]
-; AVX512F-NEXT: vpaddq %zmm0, %zmm0, %zmm0
-; AVX512F-NEXT: vpsllq %xmm1, %zmm0, %zmm0
; AVX512F-NEXT: movq %rdi, %rax
-; AVX512F-NEXT: vporq %zmm4, %zmm0, %zmm0
-; AVX512F-NEXT: vmovdqu64 %zmm0, (%rdi)
+; AVX512F-NEXT: movl $511, %ecx # imm = 0x1FF
+; AVX512F-NEXT: subl %esi, %ecx
+; AVX512F-NEXT: movq $-1, %rdx
+; AVX512F-NEXT: shlxq %rcx, %rdx, %rsi
+; AVX512F-NEXT: shrl $6, %ecx
+; AVX512F-NEXT: movl $1, %edi
+; AVX512F-NEXT: shlxq %rcx, %rdi, %rdi
+; AVX512F-NEXT: kmovw %edi, %k1
+; AVX512F-NEXT: shlxq %rcx, %rdx, %rcx
+; AVX512F-NEXT: kmovw %ecx, %k2
+; AVX512F-NEXT: vpternlogq {{.*#+}} zmm0 {%k2} {z} = -1
+; AVX512F-NEXT: vpbroadcastq %rsi, %zmm0 {%k1}
+; AVX512F-NEXT: vmovdqu64 %zmm0, (%rax)
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: ashr_signbit_i512:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: movq %rdi, %rax
-; AVX512VL-NEXT: movl %esi, %ecx
-; AVX512VL-NEXT: shrl $6, %esi
-; AVX512VL-NEXT: movl $-1, %edx
-; AVX512VL-NEXT: shlxl %esi, %edx, %edx
-; AVX512VL-NEXT: kmovd %edx, %k1
-; AVX512VL-NEXT: vmovdqa64 {{.*#+}} zmm0 = [0,0,0,0,0,0,0,9223372036854775808]
-; AVX512VL-NEXT: vpternlogd {{.*#+}} zmm1 = -1
-; AVX512VL-NEXT: vpternlogd {{.*#+}} zmm2 = -1
-; AVX512VL-NEXT: vpcompressq %zmm0, %zmm2 {%k1}
-; AVX512VL-NEXT: vpbroadcastq {{.*#+}} xmm0 = [63,63]
-; AVX512VL-NEXT: vpbroadcastq %rcx, %xmm3
-; AVX512VL-NEXT: vpand %xmm0, %xmm3, %xmm4
-; AVX512VL-NEXT: vpsrlq %xmm4, %zmm2, %zmm4
-; AVX512VL-NEXT: vpandn %xmm0, %xmm3, %xmm0
-; AVX512VL-NEXT: valignq {{.*#+}} zmm1 = zmm2[1,2,3,4,5,6,7],zmm1[0]
-; AVX512VL-NEXT: vpaddq %zmm1, %zmm1, %zmm1
-; AVX512VL-NEXT: vpsllq %xmm0, %zmm1, %zmm0
-; AVX512VL-NEXT: vporq %zmm4, %zmm0, %zmm0
-; AVX512VL-NEXT: vmovdqu64 %zmm0, (%rdi)
+; AVX512VL-NEXT: movl $511, %ecx # imm = 0x1FF
+; AVX512VL-NEXT: subl %esi, %ecx
+; AVX512VL-NEXT: movq $-1, %rdx
+; AVX512VL-NEXT: shlxq %rcx, %rdx, %rsi
+; AVX512VL-NEXT: shrl $6, %ecx
+; AVX512VL-NEXT: movl $1, %edi
+; AVX512VL-NEXT: shlxq %rcx, %rdi, %rdi
+; AVX512VL-NEXT: kmovd %edi, %k1
+; AVX512VL-NEXT: shlxq %rcx, %rdx, %rcx
+; AVX512VL-NEXT: kmovd %ecx, %k2
+; AVX512VL-NEXT: vpternlogq {{.*#+}} zmm0 {%k2} {z} = -1
+; AVX512VL-NEXT: vpbroadcastq %rsi, %zmm0 {%k1}
+; AVX512VL-NEXT: vmovdqu64 %zmm0, (%rax)
; AVX512VL-NEXT: vzeroupper
; AVX512VL-NEXT: retq
;
; AVX512VBMI-LABEL: ashr_signbit_i512:
; AVX512VBMI: # %bb.0:
; AVX512VBMI-NEXT: movq %rdi, %rax
-; AVX512VBMI-NEXT: movl %esi, %ecx
+; AVX512VBMI-NEXT: movl $511, %ecx # imm = 0x1FF
+; AVX512VBMI-NEXT: subl %esi, %ecx
+; AVX512VBMI-NEXT: movq $-1, %rdx
+; AVX512VBMI-NEXT: shlxq %rcx, %rdx, %rsi
; AVX512VBMI-NEXT: shrl $6, %ecx
-; AVX512VBMI-NEXT: movl $-1, %edx
-; AVX512VBMI-NEXT: shlxl %ecx, %edx, %ecx
-; AVX512VBMI-NEXT: kmovd %ecx, %k1
-; AVX512VBMI-NEXT: vmovdqa64 {{.*#+}} zmm0 = [0,0,0,0,0,0,0,9223372036854775808]
-; AVX512VBMI-NEXT: vpternlogd {{.*#+}} zmm1 = -1
-; AVX512VBMI-NEXT: vpcompressq %zmm0, %zmm1 {%k1}
-; AVX512VBMI-NEXT: vpbroadcastq %rsi, %zmm0
-; AVX512VBMI-NEXT: vpternlogd {{.*#+}} zmm2 = -1
-; AVX512VBMI-NEXT: valignq {{.*#+}} zmm2 = zmm1[1,2,3,4,5,6,7],zmm2[0]
-; AVX512VBMI-NEXT: vpshrdvq %zmm0, %zmm2, %zmm1
-; AVX512VBMI-NEXT: vmovdqu64 %zmm1, (%rdi)
+; AVX512VBMI-NEXT: movl $1, %edi
+; AVX512VBMI-NEXT: shlxq %rcx, %rdi, %rdi
+; AVX512VBMI-NEXT: kmovd %edi, %k1
+; AVX512VBMI-NEXT: shlxq %rcx, %rdx, %rcx
+; AVX512VBMI-NEXT: kmovd %ecx, %k2
+; AVX512VBMI-NEXT: vpternlogq {{.*#+}} zmm0 {%k2} {z} = -1
+; AVX512VBMI-NEXT: vpbroadcastq %rsi, %zmm0 {%k1}
+; AVX512VBMI-NEXT: vmovdqu64 %zmm0, (%rax)
; AVX512VBMI-NEXT: vzeroupper
; AVX512VBMI-NEXT: retq
%s = shl i512 1, 511
>From 8a7e05286739c1eb2f42aabe1af8aab7b4272912 Mon Sep 17 00:00:00 2001
From: Lewis Crawford <lcrawford at nvidia.com>
Date: Wed, 18 Mar 2026 09:31:55 +0000
Subject: [PATCH 09/33] [Instrumentation][nsan] Add maximumnum to NSAN
(#186345)
Add support for the min/maximumnum intrinsics and the corresponding
libfuncs to the NumericalStabilitySanitizer.
---
.../NumericalStabilitySanitizer.cpp | 12 ++
.../NumericalStabilitySanitizer/intrinsics.ll | 150 ++++++++++++++++++
.../NumericalStabilitySanitizer/libfuncs.ll | 150 ++++++++++++++++++
3 files changed, 312 insertions(+)
diff --git a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
index 5f895ad33d065..0b0614322d41e 100644
--- a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
@@ -1418,6 +1418,12 @@ const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
{"llvm.maximum.f32", Intrinsic::maximum, makeDoubleDoubleDouble},
{"llvm.maximum.f64", Intrinsic::maximum, makeX86FP80X86FP80X86FP80},
{"llvm.maximum.f80", Intrinsic::maximum, makeX86FP80X86FP80X86FP80},
+ {"llvm.minimumnum.f32", Intrinsic::minimumnum, makeDoubleDoubleDouble},
+ {"llvm.minimumnum.f64", Intrinsic::minimumnum, makeX86FP80X86FP80X86FP80},
+ {"llvm.minimumnum.f80", Intrinsic::minimumnum, makeX86FP80X86FP80X86FP80},
+ {"llvm.maximumnum.f32", Intrinsic::maximumnum, makeDoubleDoubleDouble},
+ {"llvm.maximumnum.f64", Intrinsic::maximumnum, makeX86FP80X86FP80X86FP80},
+ {"llvm.maximumnum.f80", Intrinsic::maximumnum, makeX86FP80X86FP80X86FP80},
{"llvm.copysign.f32", Intrinsic::copysign, makeDoubleDoubleDouble},
{"llvm.copysign.f64", Intrinsic::copysign, makeX86FP80X86FP80X86FP80},
{"llvm.copysign.f80", Intrinsic::copysign, makeX86FP80X86FP80X86FP80},
@@ -1484,6 +1490,12 @@ const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
{LibFunc_fminf, "llvm.minnum.f32"},
{LibFunc_fmin, "llvm.minnum.f64"},
{LibFunc_fminl, "llvm.minnum.f80"},
+ {LibFunc_fmaximum_numf, "llvm.maximumnum.f32"},
+ {LibFunc_fmaximum_num, "llvm.maximumnum.f64"},
+ {LibFunc_fmaximum_numl, "llvm.maximumnum.f80"},
+ {LibFunc_fminimum_numf, "llvm.minimumnum.f32"},
+ {LibFunc_fminimum_num, "llvm.minimumnum.f64"},
+ {LibFunc_fminimum_numl, "llvm.minimumnum.f80"},
{LibFunc_ceilf, "llvm.ceil.f32"},
{LibFunc_ceil, "llvm.ceil.f64"},
{LibFunc_ceill, "llvm.ceil.f80"},
diff --git a/llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll b/llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll
index b2d67bc9816d8..033a31ba12fbf 100644
--- a/llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll
+++ b/llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll
@@ -1283,6 +1283,156 @@ entry:
ret x86_fp80 %r
}
+;###############################################################
+;# minimumnum #
+;###############################################################
+declare float @llvm.minimumnum.f32(float, float) readnone
+declare double @llvm.minimumnum.f64(double, double) readnone
+declare x86_fp80 @llvm.minimumnum.f80(x86_fp80, x86_fp80) readnone
+
+define float @call_minimumnum_f32() sanitize_numerical_stability {
+; CHECK-LABEL: @call_minimumnum_f32(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.minimumnum.f32(float 1.000000e+00, float 2.000000e+00)
+; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.minimumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_float_d(float [[TMP0]], double [[TMP1]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[TMP0]] to double
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], double [[TMP4]], double [[TMP1]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_minimumnum_f32 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store double [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 8
+; CHECK-NEXT: ret float [[TMP0]]
+;
+entry:
+ %r = call float @llvm.minimumnum.f32(float 1.0, float 2.0)
+ ret float %r
+}
+
+define double @call_minimumnum_f64() sanitize_numerical_stability {
+; DQQ-LABEL: @call_minimumnum_f64(
+; DQQ-NEXT: entry:
+; DQQ-NEXT: [[TMP0:%.*]] = call double @llvm.minimumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; DQQ-NEXT: [[TMP6:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP6]] to fp128
+; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[TMP0]], fp128 [[TMP1]], i32 1, i64 0)
+; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[TMP0]] to fp128
+; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; DQQ-NEXT: store i64 ptrtoint (ptr @call_minimumnum_f64 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; DQQ-NEXT: ret double [[TMP0]]
+;
+; DLQ-LABEL: @call_minimumnum_f64(
+; DLQ-NEXT: entry:
+; DLQ-NEXT: [[TMP0:%.*]] = call double @llvm.minimumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; DLQ-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DLQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_l(double [[TMP0]], x86_fp80 [[TMP1]], i32 1, i64 0)
+; DLQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; DLQ-NEXT: [[TMP4:%.*]] = fpext double [[TMP0]] to x86_fp80
+; DLQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], x86_fp80 [[TMP4]], x86_fp80 [[TMP1]]
+; DLQ-NEXT: store i64 ptrtoint (ptr @call_minimumnum_f64 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DLQ-NEXT: store x86_fp80 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; DLQ-NEXT: ret double [[TMP0]]
+;
+entry:
+ %r = call double @llvm.minimumnum.f64(double 1.0, double 2.0)
+ ret double %r
+}
+
+define x86_fp80 @call_minimumnum_f80() sanitize_numerical_stability {
+; CHECK-LABEL: @call_minimumnum_f80(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_minimumnum_f80 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+entry:
+ %r = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+ ret x86_fp80 %r
+}
+
+;###############################################################
+;# maximumnum #
+;###############################################################
+declare float @llvm.maximumnum.f32(float, float) readnone
+declare double @llvm.maximumnum.f64(double, double) readnone
+declare x86_fp80 @llvm.maximumnum.f80(x86_fp80, x86_fp80) readnone
+
+define float @call_maximumnum_f32() sanitize_numerical_stability {
+; CHECK-LABEL: @call_maximumnum_f32(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.maximumnum.f32(float 1.000000e+00, float 2.000000e+00)
+; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maximumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_float_d(float [[TMP0]], double [[TMP1]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[TMP0]] to double
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], double [[TMP4]], double [[TMP1]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_maximumnum_f32 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store double [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 8
+; CHECK-NEXT: ret float [[TMP0]]
+;
+entry:
+ %r = call float @llvm.maximumnum.f32(float 1.0, float 2.0)
+ ret float %r
+}
+
+define double @call_maximumnum_f64() sanitize_numerical_stability {
+; DQQ-LABEL: @call_maximumnum_f64(
+; DQQ-NEXT: entry:
+; DQQ-NEXT: [[TMP0:%.*]] = call double @llvm.maximumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; DQQ-NEXT: [[TMP6:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP6]] to fp128
+; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[TMP0]], fp128 [[TMP1]], i32 1, i64 0)
+; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[TMP0]] to fp128
+; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; DQQ-NEXT: store i64 ptrtoint (ptr @call_maximumnum_f64 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; DQQ-NEXT: ret double [[TMP0]]
+;
+; DLQ-LABEL: @call_maximumnum_f64(
+; DLQ-NEXT: entry:
+; DLQ-NEXT: [[TMP0:%.*]] = call double @llvm.maximumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; DLQ-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DLQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_l(double [[TMP0]], x86_fp80 [[TMP1]], i32 1, i64 0)
+; DLQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; DLQ-NEXT: [[TMP4:%.*]] = fpext double [[TMP0]] to x86_fp80
+; DLQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], x86_fp80 [[TMP4]], x86_fp80 [[TMP1]]
+; DLQ-NEXT: store i64 ptrtoint (ptr @call_maximumnum_f64 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DLQ-NEXT: store x86_fp80 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; DLQ-NEXT: ret double [[TMP0]]
+;
+entry:
+ %r = call double @llvm.maximumnum.f64(double 1.0, double 2.0)
+ ret double %r
+}
+
+define x86_fp80 @call_maximumnum_f80() sanitize_numerical_stability {
+; CHECK-LABEL: @call_maximumnum_f80(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_maximumnum_f80 to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+entry:
+ %r = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+ ret x86_fp80 %r
+}
+
;###############################################################
;# copysign #
;###############################################################
diff --git a/llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll b/llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll
index e9ef2104fd370..6f474885cd89f 100644
--- a/llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll
+++ b/llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll
@@ -1056,6 +1056,156 @@ entry:
ret x86_fp80 %r
}
+;###############################################################
+;# fminimum_num #
+;###############################################################
+declare float @fminimum_numf(float, float)
+declare double @fminimum_num(double, double)
+declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80)
+
+define float @call_fminimum_numf() sanitize_numerical_stability {
+; CHECK-LABEL: @call_fminimum_numf(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[R:%.*]] = call float @fminimum_numf(float 1.000000e+00, float 2.000000e+00)
+; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.minimumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_fminimum_numf to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8
+; CHECK-NEXT: ret float [[R]]
+;
+entry:
+ %r = call float @fminimum_numf(float 1.0, float 2.0)
+ ret float %r
+}
+
+define double @call_fminimum_num() sanitize_numerical_stability {
+; DQQ-LABEL: @call_fminimum_num(
+; DQQ-NEXT: entry:
+; DQQ-NEXT: [[R:%.*]] = call double @fminimum_num(double 1.000000e+00, double 2.000000e+00)
+; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128
+; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0)
+; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128
+; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; DQQ-NEXT: store i64 ptrtoint (ptr @call_fminimum_num to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; DQQ-NEXT: ret double [[R]]
+;
+; DLQ-LABEL: @call_fminimum_num(
+; DLQ-NEXT: entry:
+; DLQ-NEXT: [[R:%.*]] = call double @fminimum_num(double 1.000000e+00, double 2.000000e+00)
+; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0)
+; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
+; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80
+; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]]
+; DLQ-NEXT: store i64 ptrtoint (ptr @call_fminimum_num to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16
+; DLQ-NEXT: ret double [[R]]
+;
+entry:
+ %r = call double @fminimum_num(double 1.0, double 2.0)
+ ret double %r
+}
+
+define x86_fp80 @call_fminimum_numl() sanitize_numerical_stability {
+; CHECK-LABEL: @call_fminimum_numl(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @fminimum_numl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_fminimum_numl to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+entry:
+ %r = call x86_fp80 @fminimum_numl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+ ret x86_fp80 %r
+}
+
+;###############################################################
+;# fmaximum_num #
+;###############################################################
+declare float @fmaximum_numf(float, float)
+declare double @fmaximum_num(double, double)
+declare x86_fp80 @fmaximum_numl(x86_fp80, x86_fp80)
+
+define float @call_fmaximum_numf() sanitize_numerical_stability {
+; CHECK-LABEL: @call_fmaximum_numf(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[R:%.*]] = call float @fmaximum_numf(float 1.000000e+00, float 2.000000e+00)
+; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.maximumnum.f64(double 1.000000e+00, double 2.000000e+00)
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_fmaximum_numf to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8
+; CHECK-NEXT: ret float [[R]]
+;
+entry:
+ %r = call float @fmaximum_numf(float 1.0, float 2.0)
+ ret float %r
+}
+
+define double @call_fmaximum_num() sanitize_numerical_stability {
+; DQQ-LABEL: @call_fmaximum_num(
+; DQQ-NEXT: entry:
+; DQQ-NEXT: [[R:%.*]] = call double @fmaximum_num(double 1.000000e+00, double 2.000000e+00)
+; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128
+; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0)
+; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128
+; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; DQQ-NEXT: store i64 ptrtoint (ptr @call_fmaximum_num to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; DQQ-NEXT: ret double [[R]]
+;
+; DLQ-LABEL: @call_fmaximum_num(
+; DLQ-NEXT: entry:
+; DLQ-NEXT: [[R:%.*]] = call double @fmaximum_num(double 1.000000e+00, double 2.000000e+00)
+; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0)
+; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
+; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80
+; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]]
+; DLQ-NEXT: store i64 ptrtoint (ptr @call_fmaximum_num to i64), ptr @__nsan_shadow_ret_tag, align 8
+; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16
+; DLQ-NEXT: ret double [[R]]
+;
+entry:
+ %r = call double @fmaximum_num(double 1.0, double 2.0)
+ ret double %r
+}
+
+define x86_fp80 @call_fmaximum_numl() sanitize_numerical_stability {
+; CHECK-LABEL: @call_fmaximum_numl(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @fmaximum_numl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0)
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1
+; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]]
+; CHECK-NEXT: store i64 ptrtoint (ptr @call_fmaximum_numl to i64), ptr @__nsan_shadow_ret_tag, align 8
+; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16
+; CHECK-NEXT: ret x86_fp80 [[R]]
+;
+entry:
+ %r = call x86_fp80 @fmaximum_numl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000)
+ ret x86_fp80 %r
+}
+
;###############################################################
;# ceil #
;###############################################################
>From b14bd77334f97577feddb9cd2c517a05878a71c6 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 18 Mar 2026 09:41:04 +0000
Subject: [PATCH 10/33] [VPlan] Improve code in VPlanRecipes using
VPlanPatternMatch (NFC) (#187130)
---
llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h | 12 ++++++------
llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp | 10 ++++------
2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index f52b9ba8b1c5b..7a0a1e59b1e34 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -72,7 +72,7 @@ struct specificval_ty {
specificval_ty(const VPValue *V) : Val(V) {}
- bool match(VPValue *VPV) const { return VPV == Val; }
+ bool match(const VPValue *VPV) const { return VPV == Val; }
};
inline specificval_ty m_Specific(const VPValue *VPV) { return VPV; }
@@ -84,7 +84,7 @@ struct deferredval_ty {
deferredval_ty(VPValue *const &V) : Val(V) {}
- bool match(VPValue *const V) const { return V == Val; }
+ bool match(const VPValue *const V) const { return V == Val; }
};
/// Like m_Specific(), but works if the specific value to match is determined
@@ -104,7 +104,7 @@ template <typename Pred, unsigned BitWidth = 0> struct int_pred_ty {
int_pred_ty(Pred P) : P(std::move(P)) {}
int_pred_ty() : P() {}
- bool match(VPValue *VPV) const {
+ bool match(const VPValue *VPV) const {
auto *VPI = dyn_cast<VPInstruction>(VPV);
if (VPI && VPI->getOpcode() == VPInstruction::Broadcast)
VPV = VPI->getOperand(0);
@@ -184,7 +184,7 @@ struct bind_apint {
bind_apint(const APInt *&Res) : Res(Res) {}
- bool match(VPValue *VPV) const {
+ bool match(const VPValue *VPV) const {
auto *CI = dyn_cast<VPConstantInt>(VPV);
if (!CI)
return false;
@@ -200,7 +200,7 @@ struct bind_const_int {
bind_const_int(uint64_t &Res) : Res(Res) {}
- bool match(VPValue *VPV) const {
+ bool match(const VPValue *VPV) const {
const APInt *APConst;
if (!bind_apint(APConst).match(VPV))
return false;
@@ -213,7 +213,7 @@ struct bind_const_int {
};
struct match_poison {
- bool match(VPValue *V) const {
+ bool match(const VPValue *V) const {
return isa<VPIRValue>(V) &&
isa<PoisonValue>(cast<VPIRValue>(V)->getValue());
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 401f6725677e3..659db43b03c77 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -2056,9 +2056,8 @@ InstructionCost VPHistogramRecipe::computeCost(ElementCount VF,
// a multiply, and add that into the cost.
InstructionCost MulCost =
Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, VTy, Ctx.CostKind);
- if (auto *CI = dyn_cast<VPConstantInt>(IncAmt))
- if (CI->isOne())
- MulCost = TTI::TCC_Free;
+ if (match(IncAmt, m_One()))
+ MulCost = TTI::TCC_Free;
// Find the cost of the histogram operation itself.
Type *PtrTy = VectorType::get(AddressTy, VF);
@@ -2521,9 +2520,8 @@ bool VPWidenIntOrFpInductionRecipe::isCanonical() const {
// The step may be defined by a recipe in the preheader (e.g. if it requires
// SCEV expansion), but for the canonical induction the step is required to be
// 1, which is represented as live-in.
- auto *StepC = dyn_cast<VPConstantInt>(getStepValue());
- auto *StartC = dyn_cast<VPConstantInt>(getStartValue());
- return StartC && StartC->isZero() && StepC && StepC->isOne() &&
+ return match(getStartValue(), m_ZeroInt()) &&
+ match(getStepValue(), m_One()) &&
getScalarType() == getRegion()->getCanonicalIVType();
}
>From 81ecc7f2e4a3f72b55dc1ad76b8e6f63bb35b775 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 18 Mar 2026 11:03:10 +0100
Subject: [PATCH 11/33] [lldb] Skip file cleanup to avoid permission issue in
API test (#187227)
Deleting anything in the build directory of a test-case is causing an
issue on one of the Windows bots. After the previous attempts in
ca15db1cd509c236cd8138bcd098117d0106db56 and
fdd2437af3cdc6d5fe199fcc9d991ccf503b55bd didn't help, we now skip the
file cleanup altogether.
---
lldb/test/API/symstore/TestSymStoreLocal.py | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/lldb/test/API/symstore/TestSymStoreLocal.py b/lldb/test/API/symstore/TestSymStoreLocal.py
index c1abd80b56f3d..98569d2b8c66f 100644
--- a/lldb/test/API/symstore/TestSymStoreLocal.py
+++ b/lldb/test/API/symstore/TestSymStoreLocal.py
@@ -15,15 +15,13 @@
class MockedSymStore:
"""
- Context Manager to populate a file structure equivalent to SymStore.exe in a
- temporary directory.
+ Context Manager to populate a file structure equivalent to SymStore.exe
"""
def __init__(self, test, exe, pdb):
self._test = test
self._exe = exe
self._pdb = pdb
- self._tmp = None
def get_key_pdb(self, exe):
"""
@@ -48,20 +46,19 @@ def __enter__(self):
if self._test.getDebugInfo() == "pdb":
key = self.get_key_pdb(self._exe)
self._test.assertIsNotNone(key)
- self._tmp = self._test.getBuildArtifact("tmp")
- pdb_dir = os.path.join(self._tmp, self._pdb, key)
+ symstore_dir = self._test.getBuildArtifact("symstore")
+ pdb_dir = os.path.join(symstore_dir, self._pdb, key)
os.makedirs(pdb_dir, exist_ok=True)
shutil.move(
self._test.getBuildArtifact(self._pdb),
os.path.join(pdb_dir, self._pdb),
)
- return self._tmp
+ return symstore_dir
def __exit__(self, *exc_info):
"""
- Remove symstore and reset settings
+ Reset settings
"""
- shutil.rmtree(self._tmp)
self._test.runCmd("settings clear plugin.symbol-locator.symstore")
>From 409df258fc8a213ae5635f51d49430662dcc9de1 Mon Sep 17 00:00:00 2001
From: Luke Hutton <luke.hutton at arm.com>
Date: Wed, 18 Mar 2026 10:10:20 +0000
Subject: [PATCH 12/33] [mlir][tosa][tosa-to-linalg] Fix rescale with double
rounding failing validation (#184787)
The validation pass added attribute checks on rescale rounding mode, but
the tosa-to-linalg-pipeline did not specify support for the doubleround
extension, causing rescale with doubleround to be rejected by the
validation in the tosa-to-linalg-pipeline.
One method of fixing this would be to only enable the attribute checks
when the "strictOpSpecAlignment" validation option is enabled. However,
I feel this is the wrong direction of travel. Long-term it would be nice
if the tosa-to-linalg-pipeline specified all the extensions it supports,
gracefully rejecting operations that require unsupported extensions.
Therefore, this change declares support for the doubleround extension to
fix the legalization failure with the ambition of adding more extensions
in the future.
---
.../Conversion/TosaToLinalg/TosaToLinalg.h | 3 ++-
.../TosaToLinalg/TosaToLinalgPass.cpp | 12 ++++++++-
.../TosaToLinalg/tosa-to-linalg-pipeline.mlir | 27 ++++++++++++++++++-
3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h b/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h
index 66f68ae71f271..c1d28528a2f90 100644
--- a/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h
+++ b/mlir/include/mlir/Conversion/TosaToLinalg/TosaToLinalg.h
@@ -38,7 +38,8 @@ void addTosaToLinalgPasses(
TosaToLinalgNamedOptions(),
// Note: Default to 'none' level unless otherwise specified.
std::optional<tosa::TosaValidationOptions> validationOptions =
- tosa::TosaValidationOptions{false, false});
+ tosa::TosaValidationOptions{false, false},
+ std::optional<TosaAttachTargetOptions> attachTargetOptions = std::nullopt);
/// Populates TOSA to linalg pipelines
/// Currently, this includes only the "tosa-to-linalg-pipeline".
diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp
index e7602b4508cf1..c60e3ab705722 100644
--- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp
+++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp
@@ -19,6 +19,7 @@
#include "mlir/Dialect/Math/IR/Math.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
+#include "mlir/Dialect/Tosa/IR/TargetEnv.h"
#include "mlir/Dialect/Tosa/IR/TosaOps.h"
#include "mlir/Dialect/Tosa/Transforms/Passes.h"
#include "mlir/IR/PatternMatch.h"
@@ -80,7 +81,8 @@ std::unique_ptr<Pass> mlir::tosa::createTosaToLinalg() {
void mlir::tosa::addTosaToLinalgPasses(
OpPassManager &pm, const TosaToLinalgOptions &options,
const TosaToLinalgNamedOptions &tosaToLinalgNamedOptions,
- std::optional<tosa::TosaValidationOptions> validationOptions) {
+ std::optional<tosa::TosaValidationOptions> validationOptions,
+ std::optional<TosaAttachTargetOptions> attachTargetOptions) {
// Optional decompositions are designed to benefit linalg.
if (!options.disableTosaDecompositions)
pm.addNestedPass<func::FuncOp>(
@@ -96,6 +98,14 @@ void mlir::tosa::addTosaToLinalgPasses(
pm.addNestedPass<func::FuncOp>(tosa::createTosaLayerwiseConstantFoldPass(
{options.aggressiveReduceConstant}));
pm.addNestedPass<func::FuncOp>(tosa::createTosaMakeBroadcastablePass());
+ if (!attachTargetOptions) {
+ attachTargetOptions = TosaAttachTargetOptions();
+ attachTargetOptions->profiles = {"pro_int", "pro_fp"};
+ // TODO: populate with all the extensions that the tosa->linalg conversion
+ // supports
+ attachTargetOptions->extensions = {"doubleround"};
+ }
+ pm.addPass(tosa::createTosaAttachTarget(*attachTargetOptions));
if (validationOptions)
pm.addPass(tosa::createTosaValidation(*validationOptions));
pm.addNestedPass<func::FuncOp>(tosa::createTosaToLinalg());
diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-pipeline.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-pipeline.mlir
index 74706c426ea9c..67b6aa63f2293 100644
--- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-pipeline.mlir
+++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-pipeline.mlir
@@ -1,4 +1,4 @@
-// RUN: mlir-opt %s --split-input-file --tosa-to-linalg-pipeline -verify-diagnostics
+// RUN: mlir-opt %s --split-input-file --tosa-to-linalg-pipeline -verify-diagnostics | FileCheck %s
// -----
@@ -28,3 +28,28 @@ func.func @avg_pool2d_with_unsupported_quant_type(%arg0: tensor<1x7x7x9x!quant.u
%0 = "tosa.avg_pool2d"(%arg0, %arg1, %arg2) {acc_type = i32, kernel = array<i64: 2, 2>, pad = array<i64: 0, 1, 0, 1>, stride = array<i64: 1, 1>} : (tensor<1x7x7x9x!quant.uniform<i8:f32, 0.01>>, tensor<1xi8>, tensor<1xi8>) -> tensor<1x7x7x9x!quant.uniform<i8:f32, 0.01>>
return %0 : tensor<1x7x7x9x!quant.uniform<i8:f32, 0.01>>
}
+
+// -----
+
+// CHECK-LABEL: rescale_doubleround
+func.func @rescale_doubleround(%arg0: tensor<8x9x7x14xi32>) -> tensor<8x9x7x14xi8> {
+ %0 = "tosa.const"() <{values = dense<0> : tensor<14xi32>}> : () -> tensor<14xi32>
+ %1 = "tosa.const"() <{values = dense<0> : tensor<14xi8>}> : () -> tensor<14xi8>
+ %2 = "tosa.const"() <{values = dense<0> : tensor<1xi32>}> : () -> tensor<1xi32>
+ %3 = "tosa.const"() <{values = dense<-5> : tensor<1xi8>}> : () -> tensor<1xi8>
+ // CHECK: tosa.apply_scale
+ %4 = tosa.rescale %arg0, %0, %1, %2, %3 {input_unsigned = false, output_unsigned = false, per_channel = true, rounding_mode = DOUBLE_ROUND, scale32 = true} : (tensor<8x9x7x14xi32>, tensor<14xi32>, tensor<14xi8>, tensor<1xi32>, tensor<1xi8>) -> tensor<8x9x7x14xi8>
+ return %4 : tensor<8x9x7x14xi8>
+}
+
+// -----
+
+func.func @rescale_inexactround(%arg0: tensor<8x9x7x14xi32>) -> tensor<8x9x7x14xi8> {
+ %0 = "tosa.const"() <{values = dense<0> : tensor<14xi32>}> : () -> tensor<14xi32>
+ %1 = "tosa.const"() <{values = dense<0> : tensor<14xi8>}> : () -> tensor<14xi8>
+ %2 = "tosa.const"() <{values = dense<0> : tensor<1xi32>}> : () -> tensor<1xi32>
+ %3 = "tosa.const"() <{values = dense<-5> : tensor<1xi8>}> : () -> tensor<1xi8>
+ // expected-error at +1 {{'tosa.rescale' op failed attribute check: rounding_mode = INEXACT_ROUND requires extension [inexactround]}}
+ %4 = tosa.rescale %arg0, %0, %1, %2, %3 {input_unsigned = false, output_unsigned = false, per_channel = true, rounding_mode = INEXACT_ROUND, scale32 = true} : (tensor<8x9x7x14xi32>, tensor<14xi32>, tensor<14xi8>, tensor<1xi32>, tensor<1xi8>) -> tensor<8x9x7x14xi8>
+ return %4 : tensor<8x9x7x14xi8>
+}
>From 3603a527fa9779dcf8cb5fa908158ca4b4ff8d07 Mon Sep 17 00:00:00 2001
From: Zhijie Wang <yesterda9 at gmail.com>
Date: Wed, 18 Mar 2026 03:16:18 -0700
Subject: [PATCH 13/33] [LifetimeSafety] Track origins through array subscript
and array-to-pointer decay (#186902)
Array element accesses and array-to-pointer decay were not tracked
because `CK_ArrayToPointerDecay` dropped origins and
`ArraySubscriptExpr` had no visitor. This patch adds both to propagate
origins through array operations.
Fixes #186075
---
.../Analyses/LifetimeSafety/FactsGenerator.h | 1 +
.../LifetimeSafety/FactsGenerator.cpp | 16 ++-
.../Sema/warn-lifetime-analysis-nocfg.cpp | 5 +-
.../Sema/warn-lifetime-safety-suggestions.cpp | 16 +++
clang/test/Sema/warn-lifetime-safety.cpp | 122 ++++++++++++++++++
5 files changed, 157 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
index 9bcf5193ef8fc..dfcbdc7d73007 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
@@ -51,6 +51,7 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> {
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE);
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
void VisitLambdaExpr(const LambdaExpr *LE);
+ void VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE);
private:
OriginList *getOriginsList(const ValueDecl &D);
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 888176f09c9b9..3259505584c9f 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -296,9 +296,13 @@ void FactsGenerator::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
if (Dest && Src && Dest->getLength() == Src->getLength())
flow(Dest, Src, /*Kill=*/true);
return;
+ case CK_ArrayToPointerDecay:
+ assert(Src && "Array expression should have origins as it is GL value");
+ CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
+ Dest->getOuterOriginID(), Src->getOuterOriginID(), /*Kill=*/true));
+ return;
case CK_FunctionToPointerDecay:
case CK_BuiltinFnToFnPtr:
- case CK_ArrayToPointerDecay:
// Ignore function-to-pointer decays.
return;
default:
@@ -470,6 +474,16 @@ void FactsGenerator::VisitLambdaExpr(const LambdaExpr *LE) {
}
}
+void FactsGenerator::VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE) {
+ assert(ASE->isGLValue() && "Array subscript should be a GL value");
+ OriginList *Dst = getOriginsList(*ASE);
+ assert(Dst && "Array subscript should have origins as it is a GL value");
+ OriginList *Src = getOriginsList(*ASE->getBase());
+ assert(Src && "Base of array subscript should have origins");
+ CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
+ Dst->getOuterOriginID(), Src->getOuterOriginID(), /*Kill=*/true));
+}
+
bool FactsGenerator::escapesViaReturn(OriginID OID) const {
return llvm::any_of(EscapesInCurrentBlock, [OID](const Fact *F) {
if (const auto *EF = F->getAs<ReturnEscapeFact>())
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index 4996664d26452..a725119444e2f 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -77,8 +77,9 @@ struct Y {
};
void dangligGslPtrFromTemporary() {
- MyIntPointer p = Y{}.a; // TODO
- (void)p;
+ MyIntPointer p = Y{}.a; // cfg-warning {{object whose reference is captured does not live long enough}} \
+ // cfg-note {{destroyed here}}
+ (void)p; // cfg-note {{later used here}}
}
struct DanglingGslPtrField {
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index b7e6c5951ba8b..22c4222022ebf 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -423,3 +423,19 @@ auto implicit_value_capture(int integer,
return [=]() { Foo(integer, ptr, ref, view); }; // expected-note 2 {{param returned here}}
}
} // namespace lambda_captures
+
+namespace array {
+
+struct MemberArrayReturn {
+ int arr[10];
+
+ int* getFirst() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}}
+ return &arr[0]; // expected-note {{param returned here}}
+ }
+
+ int* getData() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}}
+ return arr; // expected-note {{param returned here}}
+ }
+};
+
+} // namespace array
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index 7fec336fad8be..bd09bb70e9a11 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -1980,3 +1980,125 @@ void outer_pointer_outlives_inner_pointee() {
}
} // namespace LoopLocalPointers
+
+namespace array {
+
+void element_use_after_scope() {
+ int* p;
+ {
+ int a[10]{};
+ p = &a[2]; // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)*p; // expected-note {{later used here}}
+}
+
+int* element_use_after_return() {
+ int a[10]{};
+ int* p = &a[0]; // expected-warning {{address of stack memory is returned later}}
+ return p; // expected-note {{returned here}}
+}
+
+void element_use_same_scope() {
+ int a[10]{};
+ int* p = &a[0];
+ (void)*p;
+}
+
+void element_reassigned_safe() {
+ int safe[10]{};
+ int* p;
+ {
+ int a[10]{};
+ p = &a[0];
+ }
+ p = &safe[0]; // Rescued.
+ (void)*p;
+}
+
+void multidimensional_use_after_scope() {
+ int* p;
+ {
+ int a[3][4]{};
+ p = &a[1][2]; // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)*p; // expected-note {{later used here}}
+}
+
+void member_array_element_use_after_scope() {
+ struct S {
+ int arr[10];
+ int b;
+ };
+ int* p;
+ {
+ S s;
+ p = &s.arr[0]; // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)*p; // expected-note {{later used here}}
+}
+
+void array_of_pointers_use_after_scope() {
+ int** p;
+ {
+ int* a[10]{};
+ p = a; // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)*p; // expected-note {{later used here}}
+}
+
+void reversed_subscript_use_after_scope() {
+ int* p;
+ {
+ int a[10]{};
+ p = &(0[a]); // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)*p; // expected-note {{later used here}}
+}
+
+int* return_decayed_array() {
+ int a[10]{};
+ int *p = a; // expected-warning {{address of stack memory is returned later}}
+ return p; // expected-note {{returned here}}
+}
+
+int* param_array_element(int a[], int n) {
+ return &a[n];
+}
+
+int* static_array() {
+ static int a[10]{};
+ return &a[1];
+}
+
+// FIXME: Pointer arithmetic is not yet tracked.
+void pointer_arithmetic_use_after_scope() {
+ int* p;
+ {
+ int a[10]{};
+ p = a + 5;
+ }
+ (void)*p; // Should warn.
+}
+
+// FIXME: Copying a pointer value out of an array element is not tracked.
+void copy_pointer_from_array_use_after_scope() {
+ int* q;
+ {
+ int x = 0;
+ int* arr[10] = {&x};
+ q = arr[0];
+ }
+ (void)*q; // Should warn.
+}
+
+// FIXME: A pointer inside an array becoming dangling is not detected.
+void pointer_in_array_use_after_scope() {
+ int* arr[10];
+ {
+ int x = 0;
+ arr[0] = &x;
+ }
+ (void)*arr[0]; // Should warn.
+}
+
+} // namespace array
>From a75c87c0a36d225464904daae0e31135c27c8d0a Mon Sep 17 00:00:00 2001
From: Emimendoza <emiliomendozareyes at gmail.com>
Date: Wed, 18 Mar 2026 06:23:33 -0400
Subject: [PATCH 14/33] [mlir][spirv] add ExecutionModeIdOp (#186241)
Adds OpExecutionModeId from spirv 1.2
---------
Co-authored-by: Jakub Kuderski <kubakuderski at gmail.com>
---
.../mlir/Dialect/SPIRV/IR/SPIRVBase.td | 2 +
.../Dialect/SPIRV/IR/SPIRVStructureOps.td | 65 +++++++++++++++++
mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp | 70 +++++++++++++++++++
.../SPIRV/Deserialization/DeserializeOps.cpp | 37 ++++++++++
.../SPIRV/Serialization/SerializeOps.cpp | 28 ++++++++
mlir/test/Dialect/SPIRV/IR/structure-ops.mlir | 68 ++++++++++++++++++
mlir/test/Target/SPIRV/execution-mode-id.mlir | 18 +++++
7 files changed, 288 insertions(+)
create mode 100644 mlir/test/Target/SPIRV/execution-mode-id.mlir
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
index fc9e2f11092e6..8badb84a879fa 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
@@ -4583,6 +4583,7 @@ def SPIRV_OC_OpGroupUMax : I32EnumAttrCase<"OpGroupUMax", 2
def SPIRV_OC_OpGroupSMax : I32EnumAttrCase<"OpGroupSMax", 271>;
def SPIRV_OC_OpNoLine : I32EnumAttrCase<"OpNoLine", 317>;
def SPIRV_OC_OpModuleProcessed : I32EnumAttrCase<"OpModuleProcessed", 330>;
+def SPIRV_OC_OpExecutionModeId : I32EnumAttrCase<"OpExecutionModeId", 331>;
def SPIRV_OC_OpGroupNonUniformElect : I32EnumAttrCase<"OpGroupNonUniformElect", 333>;
def SPIRV_OC_OpGroupNonUniformAll : I32EnumAttrCase<"OpGroupNonUniformAll", 334>;
def SPIRV_OC_OpGroupNonUniformAny : I32EnumAttrCase<"OpGroupNonUniformAny", 335>;
@@ -4726,6 +4727,7 @@ def SPIRV_OpcodeAttr :
SPIRV_OC_OpGroupFAdd, SPIRV_OC_OpGroupFMin, SPIRV_OC_OpGroupUMin,
SPIRV_OC_OpGroupSMin, SPIRV_OC_OpGroupFMax, SPIRV_OC_OpGroupUMax,
SPIRV_OC_OpGroupSMax, SPIRV_OC_OpNoLine, SPIRV_OC_OpModuleProcessed,
+ SPIRV_OC_OpExecutionModeId,
SPIRV_OC_OpGroupNonUniformElect, SPIRV_OC_OpGroupNonUniformAll,
SPIRV_OC_OpGroupNonUniformAny, SPIRV_OC_OpGroupNonUniformAllEqual,
SPIRV_OC_OpGroupNonUniformBroadcast, SPIRV_OC_OpGroupNonUniformBroadcastFirst,
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
index 9959f0bec781e..6899fc2dabc70 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
@@ -290,6 +290,71 @@ def SPIRV_ExecutionModeOp : SPIRV_Op<"ExecutionMode", [InModuleScope]> {
// -----
+def SPIRV_ExecutionModeIdOp : SPIRV_Op<"ExecutionModeId", []> {
+ let summary = [{
+ Declare an execution mode for an entry point, using <id>s as Extra
+ Operands.
+ }];
+
+ let description = [{
+ Entry Point must be the Entry Point <id> operand of an OpEntryPoint
+ instruction.
+
+ Mode is the execution mode. See Execution Mode.
+
+ This instruction is only valid if the Mode operand is an execution mode
+ that takes Extra Operands that are <id> operands. Otherwise, use
+ OpExecutionMode.
+
+ <!-- End of AutoGen section -->
+
+ ```
+ execution-mode ::= "Invocations" | "SpacingEqual" |
+ <and other SPIR-V execution modes...>
+ execution-mode-id-op ::= `spirv.ExecutionMode ` ssa-use execution-mode
+ symbol-reference (`, ` symbol-reference)*
+ ```
+
+ #### Example:
+
+ ```mlir
+ spirv.ExecutionModeId @foo "LocalSizeId" @var0, @var1, @var2
+ spirv.ExecutionModeId @bar "LocalSizeHintId" @x, @y, @z
+ ```
+ }];
+
+ let availability = [
+ MinVersion<SPIRV_V_1_2>,
+ MaxVersion<SPIRV_V_1_6>,
+ Extension<[]>,
+ Capability<[]>
+ ];
+
+ let arguments = (ins
+ FlatSymbolRefAttr:$fn,
+ SPIRV_ExecutionModeAttr:$execution_mode,
+ SymbolRefArrayAttr:$values
+ );
+
+ let results = (outs);
+
+ let hasVerifier = 1;
+
+ let autogenSerialization = 0;
+
+ let builders = [OpBuilder<(ins "spirv::FuncOp":$function,
+ "spirv::ExecutionMode":$executionMode,
+ "ArrayRef<Attribute>":$params),
+ [{
+ build($_builder, $_state,
+ SymbolRefAttr::get(function),
+ ExecutionModeAttr::get($_builder.getContext(), executionMode),
+ $_builder.getArrayAttr(params));
+ }]>];
+}
+
+// -----
+
def SPIRV_FuncOp : SPIRV_Op<"func", [
AutomaticAllocationScope, FunctionOpInterface,
InModuleScope, IsolatedFromAbove
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
index 41a0e8558ed89..cecc8c2194237 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
@@ -919,6 +919,76 @@ void spirv::ExecutionModeOp::print(OpAsmPrinter &printer) {
printer << ", " << llvm::interleaved(values.getAsValueRange<IntegerAttr>());
}
+//===----------------------------------------------------------------------===//
+// spirv.ExecutionModeId
+//===----------------------------------------------------------------------===//
+
+ParseResult spirv::ExecutionModeIdOp::parse(OpAsmParser &parser,
+ OperationState &result) {
+ ExecutionMode execMode;
+ if (Attribute fn;
+ parser.parseAttribute(fn, kFnNameAttrName, result.attributes) ||
+ parseEnumStrAttr<ExecutionModeAttr>(execMode, parser, result)) {
+ return failure();
+ }
+
+ SmallVector<Attribute, 4> values;
+ if (parser.parseCommaSeparatedList([&]() -> ParseResult {
+ FlatSymbolRefAttr attr;
+ if (parser.parseAttribute(attr))
+ return failure();
+ values.push_back(attr);
+ return success();
+ })) {
+ return failure();
+ }
+
+ StringRef valuesAttrName = getValuesAttrName(result.name);
+ ArrayAttr valuesAttr = parser.getBuilder().getArrayAttr(values);
+ result.addAttribute(valuesAttrName, valuesAttr);
+ return success();
+}
+
+void spirv::ExecutionModeIdOp::print(OpAsmPrinter &printer) {
+ printer << " ";
+ printer.printSymbolName(getFn());
+ printer << " \"" << stringifyExecutionMode(getExecutionMode()) << "\" ";
+
+ llvm::interleaveComma(
+ getValues().getAsValueRange<FlatSymbolRefAttr>(), printer,
+ [&](StringRef value) { printer.printSymbolName(value); });
+}
+
+LogicalResult spirv::ExecutionModeIdOp::verify() {
+ // Valid as of SPIRV 1.6
+ switch (getExecutionMode()) {
+ case ExecutionMode::SubgroupsPerWorkgroupId:
+ case ExecutionMode::LocalSizeId:
+ case ExecutionMode::LocalSizeHintId:
+ break;
+ default:
+ return emitOpError("expected ExecutionMode that takes extra operands that "
+ "are <id> operands, got: ")
+ << stringifyExecutionMode(getExecutionMode());
+ }
+
+ if (getValues().empty())
+ return emitOpError("expected at least one value operand");
+
+ for (Attribute value : getValues()) {
+ auto valueSymbol = dyn_cast<FlatSymbolRefAttr>(value);
+ if (!valueSymbol)
+ return emitOpError("expected value operands to be symbol reference");
+ Operation *valueOp = SymbolTable::lookupNearestSymbolFrom(
+ (*this)->getParentOp(), valueSymbol);
+ if (!valueOp)
+ return emitOpError("cannot find symbol referenced by value operand: ")
+ << valueSymbol.getValue();
+ }
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// spirv.func
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
index 5b04a14a78036..cc6302126d64a 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
+++ b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
@@ -147,6 +147,7 @@ LogicalResult spirv::Deserializer::processInstruction(
return processMemoryModel(operands);
case spirv::Opcode::OpEntryPoint:
case spirv::Opcode::OpExecutionMode:
+ case spirv::Opcode::OpExecutionModeId:
if (deferInstructions) {
deferredInstructions.emplace_back(opcode, operands);
return success();
@@ -453,6 +454,42 @@ Deserializer::processOp<spirv::ExecutionModeOp>(ArrayRef<uint32_t> words) {
return success();
}
+template <>
+LogicalResult
+Deserializer::processOp<spirv::ExecutionModeIdOp>(ArrayRef<uint32_t> words) {
+ unsigned wordIndex = 0;
+ unsigned const wordsSize = words.size();
+ if (wordIndex >= wordsSize)
+ return emitError(unknownLoc,
+ "missing function result <id> in OpExecutionModeId");
+
+ // Get the function <id> to get the name of the function.
+ uint32_t fnID = words[wordIndex++];
+ FuncOp fn = getFunction(fnID);
+ if (!fn)
+ return emitError(unknownLoc, "no function matching <id> ") << fnID;
+
+ // Get the Execution mode.
+ if (wordIndex >= wordsSize)
+ return emitError(unknownLoc, "missing Execution Mode in OpExecutionModeId");
+
+ ExecutionModeAttr execMode = spirv::ExecutionModeAttr::get(
+ context, static_cast<spirv::ExecutionMode>(words[wordIndex++]));
+
+ // Get the values.
+ SmallVector<Attribute, 4> attrListElems;
+ while (wordIndex < words.size()) {
+ std::string id = getSpecConstantSymbol(words[wordIndex++]);
+ attrListElems.push_back(FlatSymbolRefAttr::get(context, id));
+ }
+ ArrayAttr values = opBuilder.getArrayAttr(attrListElems);
+ spirv::ExecutionModeIdOp::create(
+ opBuilder, unknownLoc,
+ SymbolRefAttr::get(opBuilder.getContext(), fn.getName()), execMode,
+ values);
+ return success();
+}
+
template <>
LogicalResult
Deserializer::processOp<spirv::FunctionCallOp>(ArrayRef<uint32_t> operands) {
diff --git a/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp b/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
index b78fac532d8c5..a2c942d4188e7 100644
--- a/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
+++ b/mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
@@ -884,6 +884,34 @@ Serializer::processOp<spirv::ExecutionModeOp>(spirv::ExecutionModeOp op) {
return success();
}
+template <>
+LogicalResult
+Serializer::processOp<spirv::ExecutionModeIdOp>(spirv::ExecutionModeIdOp op) {
+ SmallVector<uint32_t, 4> operands;
+ // Add the function <id>.
+ uint32_t funcID = getFunctionID(op.getFn());
+ if (!funcID)
+ return op.emitError("missing <id> for function ")
+ << op.getFn()
+ << "; function needs to be serialized before ExecutionModeIdOp is "
+ "serialized";
+
+ operands.push_back(funcID);
+ operands.push_back(static_cast<uint32_t>(op.getExecutionMode()));
+
+ for (Attribute refVal : op.getValues().getValue()) {
+ uint32_t id = getSpecConstID(cast<FlatSymbolRefAttr>(refVal).getValue());
+ if (!id)
+ return op.emitError("unknown <id> for specialization constant ")
+ << cast<FlatSymbolRefAttr>(refVal).getValue();
+
+ operands.push_back(id);
+ }
+ encodeInstructionInto(executionModes, spirv::Opcode::OpExecutionModeId,
+ operands);
+ return success();
+}
+
template <>
LogicalResult
Serializer::processOp<spirv::FunctionCallOp>(spirv::FunctionCallOp op) {
diff --git a/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir b/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
index 7e37826795d83..e12b70cc5c139 100644
--- a/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
@@ -327,6 +327,74 @@ spirv.module Logical GLSL450 {
// -----
+//===----------------------------------------------------------------------===//
+// spirv.ExecutionModeId
+//===----------------------------------------------------------------------===//
+
+spirv.module Logical GLSL450 {
+ spirv.SpecConstant @x = 3 : i32
+ spirv.SpecConstant @y = 4 : i32
+ spirv.SpecConstant @z = 5 : i32
+ spirv.func @do_nothing() -> () "None" {
+ spirv.Return
+ }
+ spirv.EntryPoint "GLCompute" @do_nothing
+ // CHECK: spirv.ExecutionModeId {{@.*}} "LocalSizeHintId" @x, @y, @z
+ spirv.ExecutionModeId @do_nothing "LocalSizeHintId" @x, @y, @z
+}
+
+// -----
+
+spirv.module Logical GLSL450 {
+ spirv.func @do_nothing() -> () "None" {
+ spirv.Return
+ }
+ spirv.EntryPoint "GLCompute" @do_nothing
+ // expected-error @+1 {{expected attribute value}}
+ spirv.ExecutionModeId @do_nothing "LocalSizeId"
+}
+
+// -----
+
+spirv.module Logical GLSL450 {
+ spirv.SpecConstant @x = 3 : i32
+ spirv.func @do_nothing() -> () "None" {
+ spirv.Return
+ }
+ spirv.EntryPoint "GLCompute" @do_nothing
+ // expected-error @+1 {{'spirv.ExecutionModeId' op expected ExecutionMode that takes extra operands that are <id> operands, got: ContractionOff}}
+ spirv.ExecutionModeId @do_nothing "ContractionOff" @x
+}
+
+// -----
+
+spirv.module Logical GLSL450 {
+ spirv.SpecConstant @x = 3 : i32
+ spirv.SpecConstant @y = 4 : i32
+ spirv.SpecConstant @z = 5 : i32
+ spirv.func @do_nothing() -> () "None" {
+ spirv.Return
+ }
+ spirv.EntryPoint "GLCompute" @do_nothing
+ // expected-error @+1 {{custom op 'spirv.ExecutionModeId' invalid execution_mode attribute specification: "GLCompute"}}
+ spirv.ExecutionModeId @do_nothing "GLCompute" @x, @y, @z
+}
+
+// -----
+
+spirv.module Logical GLSL450 {
+ spirv.SpecConstant @x = 3 : i32
+ spirv.SpecConstant @y = 4 : i32
+ spirv.func @do_nothing() -> () "None" {
+ spirv.Return
+ }
+ spirv.EntryPoint "GLCompute" @do_nothing
+ // expected-error @+1 {{custom op 'spirv.ExecutionModeId' invalid kind of attribute specified}}
+ spirv.ExecutionModeId @do_nothing "LocalSizeId" @x, @y, 2
+}
+
+// -----
+
//===----------------------------------------------------------------------===//
// spirv.func
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Target/SPIRV/execution-mode-id.mlir b/mlir/test/Target/SPIRV/execution-mode-id.mlir
new file mode 100644
index 0000000000000..f5975655fcda3
--- /dev/null
+++ b/mlir/test/Target/SPIRV/execution-mode-id.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-translate --no-implicit-module --test-spirv-roundtrip %s | FileCheck %s
+
+// RUN: %if spirv-tools %{ rm -rf %t %}
+// RUN: %if spirv-tools %{ mkdir %t %}
+// RUN: %if spirv-tools %{ mlir-translate --no-implicit-module --serialize-spirv --spirv-save-validation-files-with-prefix=%t/module %s %}
+// RUN: %if spirv-tools %{ spirv-val %t %}
+
+spirv.module Logical GLSL450 requires #spirv.vce<v1.2, [Shader], []> {
+ spirv.SpecConstant @x = 3 : i32
+ spirv.SpecConstant @y = 4 : i32
+ spirv.SpecConstant @z = 5 : i32
+ spirv.func @foo() -> () "None" {
+ spirv.Return
+ }
+ spirv.EntryPoint "GLCompute" @foo
+ // CHECK: spirv.ExecutionModeId @foo "LocalSizeId" @x, @y, @z
+ spirv.ExecutionModeId @foo "LocalSizeId" @x, @y, @z
+}
>From 3a7826fb13689ae758525ded483564a14962416e Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Wed, 18 Mar 2026 14:30:28 +0400
Subject: [PATCH 15/33] [clang] Enable '-verify-directives' mode in C++ DR
tests (#187219)
This patch enables recently implemented `-verify-directives` mode
(#179835) in C++ DR tests to automate some of the work I've been doing
manually while reviewing PRs touching those tests. As highlighted in
that PR, all the errors this mode found were addressed in #179813 and
#179674, so this PR just flips the switch.
---
clang/test/CXX/drs/cwg0xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg10xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg11xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg12xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg13xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg14xx.cpp | 30 +++++++++++++++---------------
clang/test/CXX/drs/cwg15xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg16xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg1736.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg17xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg18xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg19xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg1xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg20xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg2149.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg21xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg22xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg2335.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg23xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg24xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg25xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg2630.cpp | 12 ++++++------
clang/test/CXX/drs/cwg26xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg273.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg27xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg28xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg29xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg2xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg30xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg3xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg4xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg5xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg6xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg787.cpp | 15 ++++++++-------
clang/test/CXX/drs/cwg7xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg8xx.cpp | 14 +++++++-------
clang/test/CXX/drs/cwg9xx.cpp | 14 +++++++-------
37 files changed, 267 insertions(+), 266 deletions(-)
diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp
index 3f33e8d3dcf33..ea1daee25610c 100644
--- a/clang/test/CXX/drs/cwg0xx.cpp
+++ b/clang/test/CXX/drs/cwg0xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify=expected,cxx98,cxx98-14
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify=expected,since-cxx11,cxx98-14,cxx11-14
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify=expected,since-cxx11,cxx98-14,cxx11-14
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify-directives -verify=expected,cxx98,cxx98-14
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify-directives -verify=expected,since-cxx11,cxx98-14,cxx11-14
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify-directives -verify=expected,since-cxx11,cxx98-14,cxx11-14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -verify-directives -verify=expected,since-cxx11,since-cxx17
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg10xx.cpp b/clang/test/CXX/drs/cwg10xx.cpp
index 7802dd0d32a2a..1f190fb5310be 100644
--- a/clang/test/CXX/drs/cwg10xx.cpp
+++ b/clang/test/CXX/drs/cwg10xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14
namespace std {
__extension__ typedef __SIZE_TYPE__ size_t;
diff --git a/clang/test/CXX/drs/cwg11xx.cpp b/clang/test/CXX/drs/cwg11xx.cpp
index 4d05da400273d..4d72dd99575f1 100644
--- a/clang/test/CXX/drs/cwg11xx.cpp
+++ b/clang/test/CXX/drs/cwg11xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
namespace cwg1110 { // cwg1110: 3.1
#if __cplusplus >= 201103L
diff --git a/clang/test/CXX/drs/cwg12xx.cpp b/clang/test/CXX/drs/cwg12xx.cpp
index 5bce8e2262976..2b143706842e3 100644
--- a/clang/test/CXX/drs/cwg12xx.cpp
+++ b/clang/test/CXX/drs/cwg12xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23
// cwg1200: na
diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp
index 339a972fcca02..a26586408231a 100644
--- a/clang/test/CXX/drs/cwg13xx.cpp
+++ b/clang/test/CXX/drs/cwg13xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11
__extension__ typedef __SIZE_TYPE__ size_t;
diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp
index 914b6b110b4a3..afa4bc9d8179a 100644
--- a/clang/test/CXX/drs/cwg14xx.cpp
+++ b/clang/test/CXX/drs/cwg14xx.cpp
@@ -1,18 +1,18 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-17,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx20
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx20
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx20
-
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify=expected
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify=expected,cxx11-17,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify=expected,since-cxx11,since-cxx14,since-cxx20
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify=expected,since-cxx11,since-cxx14,since-cxx20
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
+
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
namespace cwg1413 { // cwg1413: 12
template<int> struct Check {
diff --git a/clang/test/CXX/drs/cwg15xx.cpp b/clang/test/CXX/drs/cwg15xx.cpp
index bdede99cc60b6..5a9b80ed028c4 100644
--- a/clang/test/CXX/drs/cwg15xx.cpp
+++ b/clang/test/CXX/drs/cwg15xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx11,cxx11-14
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx11,cxx11-14,cxx14-17
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx20,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx11,cxx11-14
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx11,cxx11-14,cxx14-17
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx20,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index 6194ee9c1523c..673916ee40d6f 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx98-14,since-cxx11,cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx98-14,since-cxx11,cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg1736.cpp b/clang/test/CXX/drs/cwg1736.cpp
index 25b9fcb747ec7..14c840677b1f7 100644
--- a/clang/test/CXX/drs/cwg1736.cpp
+++ b/clang/test/CXX/drs/cwg1736.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
// cxx98-no-diagnostics
diff --git a/clang/test/CXX/drs/cwg17xx.cpp b/clang/test/CXX/drs/cwg17xx.cpp
index 6997625f606c1..46693eaa5a169 100644
--- a/clang/test/CXX/drs/cwg17xx.cpp
+++ b/clang/test/CXX/drs/cwg17xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
namespace cwg1710 { // cwg1710: no
// FIXME: all of the following is well-formed
diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp
index d111d053ec66c..ebee9bc4c3e16 100644
--- a/clang/test/CXX/drs/cwg18xx.cpp
+++ b/clang/test/CXX/drs/cwg18xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx98-14,cxx11-17,since-cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx14,cxx98-14,cxx11-17,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14,cxx17
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx98-14,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx14,cxx98-14,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14,cxx17
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg19xx.cpp b/clang/test/CXX/drs/cwg19xx.cpp
index 449ae5129e095..8162f9caa8f15 100644
--- a/clang/test/CXX/drs/cwg19xx.cpp
+++ b/clang/test/CXX/drs/cwg19xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-11,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-11,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-11,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-11,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14,since-cxx11
namespace std {
struct type_info;
diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp
index ebe9ecdb4e722..08e09d4a45095 100644
--- a/clang/test/CXX/drs/cwg1xx.cpp
+++ b/clang/test/CXX/drs/cwg1xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98,cxx98-11,cxx98-14,cxx98-17
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx98-11,cxx98-14,cxx98-17,cxx11-14
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx98-14,cxx98-17,cxx11-14
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17,cxx98-17
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98,cxx98-11,cxx98-14,cxx98-17
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx98-11,cxx98-14,cxx98-17,cxx11-14
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx98-14,cxx98-17,cxx11-14
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,cxx98-17
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg20xx.cpp b/clang/test/CXX/drs/cwg20xx.cpp
index a9c5616b2aa4e..75b4094283db0 100644
--- a/clang/test/CXX/drs/cwg20xx.cpp
+++ b/clang/test/CXX/drs/cwg20xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx20
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx20
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg2149.cpp b/clang/test/CXX/drs/cwg2149.cpp
index 4662fa0a2e3c6..979f5ff6c0078 100644
--- a/clang/test/CXX/drs/cwg2149.cpp
+++ b/clang/test/CXX/drs/cwg2149.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98 -ast-dump | FileCheck %s --check-prefixes CXX98
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98 -ast-dump | FileCheck %s --check-prefixes CXX98
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg21xx.cpp b/clang/test/CXX/drs/cwg21xx.cpp
index ab50f80cff275..3f200c853f0d9 100644
--- a/clang/test/CXX/drs/cwg21xx.cpp
+++ b/clang/test/CXX/drs/cwg21xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,since-cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,since-cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg22xx.cpp b/clang/test/CXX/drs/cwg22xx.cpp
index 595e041fd42cd..6d51afcdda743 100644
--- a/clang/test/CXX/drs/cwg22xx.cpp
+++ b/clang/test/CXX/drs/cwg22xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
namespace cwg2211 { // cwg2211: 8
diff --git a/clang/test/CXX/drs/cwg2335.cpp b/clang/test/CXX/drs/cwg2335.cpp
index f6761d487ebad..39970b3e7d0fc 100644
--- a/clang/test/CXX/drs/cwg2335.cpp
+++ b/clang/test/CXX/drs/cwg2335.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-11
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx14
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-11
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx14
// cxx98-11-no-diagnostics
diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp
index 507e851dcea84..cfd78465c0dbe 100644
--- a/clang/test/CXX/drs/cwg23xx.cpp
+++ b/clang/test/CXX/drs/cwg23xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-14,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-14,since-cxx11,since-cxx14
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-14,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-14,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
namespace std {
__extension__ typedef __SIZE_TYPE__ size_t;
diff --git a/clang/test/CXX/drs/cwg24xx.cpp b/clang/test/CXX/drs/cwg24xx.cpp
index c71cf8cde82f2..8d0c2c064199f 100644
--- a/clang/test/CXX/drs/cwg24xx.cpp
+++ b/clang/test/CXX/drs/cwg24xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -pedantic-errors %s -verify=expected,cxx98-14
-// RUN: %clang_cc1 -std=c++11 -pedantic-errors %s -verify=expected,cxx98-14
-// RUN: %clang_cc1 -std=c++14 -pedantic-errors %s -verify=expected,cxx98-14
-// RUN: %clang_cc1 -std=c++17 -pedantic-errors %s -verify=expected,since-cxx17
-// RUN: %clang_cc1 -std=c++20 -pedantic-errors %s -verify=expected,since-cxx20,since-cxx17
-// RUN: %clang_cc1 -std=c++23 -pedantic-errors %s -verify=expected,since-cxx20,since-cxx17
-// RUN: %clang_cc1 -std=c++2c -pedantic-errors %s -verify=expected,since-cxx20,since-cxx17
+// RUN: %clang_cc1 -std=c++98 -pedantic-errors %s -verify-directives -verify=expected,cxx98-14
+// RUN: %clang_cc1 -std=c++11 -pedantic-errors %s -verify-directives -verify=expected,cxx98-14
+// RUN: %clang_cc1 -std=c++14 -pedantic-errors %s -verify-directives -verify=expected,cxx98-14
+// RUN: %clang_cc1 -std=c++17 -pedantic-errors %s -verify-directives -verify=expected,since-cxx17
+// RUN: %clang_cc1 -std=c++20 -pedantic-errors %s -verify-directives -verify=expected,since-cxx20,since-cxx17
+// RUN: %clang_cc1 -std=c++23 -pedantic-errors %s -verify-directives -verify=expected,since-cxx20,since-cxx17
+// RUN: %clang_cc1 -std=c++2c -pedantic-errors %s -verify-directives -verify=expected,since-cxx20,since-cxx17
// cwg2406 is in cwg2406.cpp
diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp
index 4734ba675cdf4..9f83a17d4b1c3 100644
--- a/clang/test/CXX/drs/cwg25xx.cpp
+++ b/clang/test/CXX/drs/cwg25xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-14,since-cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx20
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx20,since-cxx23
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx20,since-cxx23
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-14,since-cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx20
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx20,since-cxx23
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx20,since-cxx23
namespace std {
struct type_info{};
diff --git a/clang/test/CXX/drs/cwg2630.cpp b/clang/test/CXX/drs/cwg2630.cpp
index 58df2b3b3ffdb..c7672e8a66543 100644
--- a/clang/test/CXX/drs/cwg2630.cpp
+++ b/clang/test/CXX/drs/cwg2630.cpp
@@ -1,10 +1,10 @@
// RUN: split-file --leading-lines %s %t
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
+// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
+// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
+// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
+// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
+// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
+// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
//--- module.cppm
// expected-no-diagnostics
diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index a739eb422543f..5fe409a3b2905 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify=expected,cxx98
-// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify=expected,since-cxx11,cxx11
-// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify=expected,since-cxx11,since-cxx20
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify=expected,since-cxx11,since-cxx20,since-cxx23
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors %s -verify=expected,since-cxx11,since-cxx20,since-cxx23
+// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected,cxx98
+// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected,since-cxx11,cxx11
+// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected,since-cxx11,since-cxx20
+// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected,since-cxx11,since-cxx20,since-cxx23
+// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected,since-cxx11,since-cxx20,since-cxx23
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg273.cpp b/clang/test/CXX/drs/cwg273.cpp
index 67b86cfa27f7c..d5c505aebe1ad 100644
--- a/clang/test/CXX/drs/cwg273.cpp
+++ b/clang/test/CXX/drs/cwg273.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
// expected-no-diagnostics
diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp
index d74d42a010dc9..ae5874ce3c46d 100644
--- a/clang/test/CXX/drs/cwg27xx.cpp
+++ b/clang/test/CXX/drs/cwg27xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98 %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20 %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx23 %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx23,since-cxx26 %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98 %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20 %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx23 %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx23,since-cxx26 %s
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp
index f836999fb29ec..9ec3cc5a1a346 100644
--- a/clang/test/CXX/drs/cwg28xx.cpp
+++ b/clang/test/CXX/drs/cwg28xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98 %s
-// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx11-23 %s
-// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx11-23 %s
-// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx11-23 %s
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx11-23,since-cxx20 %s
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx11-23,since-cxx20,since-cxx23 %s
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx20,since-cxx23,since-cxx26 %s
+// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98 %s
+// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx11-23 %s
+// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx11-23 %s
+// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx11-23 %s
+// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx11-23,since-cxx20 %s
+// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx11-23,since-cxx20,since-cxx23 %s
+// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx20,since-cxx23,since-cxx26 %s
int main() {} // required for cwg2811
diff --git a/clang/test/CXX/drs/cwg29xx.cpp b/clang/test/CXX/drs/cwg29xx.cpp
index 7dc8c78cc3dec..54f5547a1629d 100644
--- a/clang/test/CXX/drs/cwg29xx.cpp
+++ b/clang/test/CXX/drs/cwg29xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98 %s
-// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11 %s
-// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11 %s
-// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11 %s
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx20 %s
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx20,since-cxx23 %s
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx20,since-cxx23,since-cxx26 %s
+// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98 %s
+// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11 %s
+// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11 %s
+// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11 %s
+// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx20 %s
+// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx20,since-cxx23 %s
+// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx20,since-cxx23,since-cxx26 %s
// cxx98-no-diagnostics
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index 122c41f445cb0..427320082a450 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98,cxx98-11,cxx98-14,cxx98-17
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,cxx98-11,cxx98-14,cxx98-17
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,cxx98-14,cxx98-17
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17,cxx98-17
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98,cxx98-11,cxx98-14,cxx98-17
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx98-11,cxx98-14,cxx98-17
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,cxx98-14,cxx98-17
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,cxx98-17
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
typedef __decltype(sizeof(0)) size_t;
diff --git a/clang/test/CXX/drs/cwg30xx.cpp b/clang/test/CXX/drs/cwg30xx.cpp
index f4d3e93b11e19..356c2cd68b4b7 100644
--- a/clang/test/CXX/drs/cwg30xx.cpp
+++ b/clang/test/CXX/drs/cwg30xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected %s
+// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
+// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected %s
namespace cwg3005 { // cwg3005: 21
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index fe51affe6efdc..041d56ea3a1db 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx98
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx11-14,since-cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx11-14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-17,cxx98-20,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-20,cxx20-23,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx20-23,cxx23,since-cxx11,since-cxx17,since-cxx23
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx20-23,cxx23,since-cxx11,since-cxx17,since-cxx23
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx98
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx11-14,since-cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx11-14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-17,cxx98-20,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-20,cxx20-23,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx20-23,cxx23,since-cxx11,since-cxx17,since-cxx23
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-linux-gnu %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx20-23,cxx23,since-cxx11,since-cxx17,since-cxx23
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp
index 55a01ea1bbf11..4f63b9ac34fb2 100644
--- a/clang/test/CXX/drs/cwg4xx.cpp
+++ b/clang/test/CXX/drs/cwg4xx.cpp
@@ -1,10 +1,10 @@
-// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98-17,cxx98
-// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98-17,since-cxx11
-// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98-17,since-cxx11
-// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,cxx98-17,since-cxx11
-// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx17,since-cxx11
-// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx17,since-cxx11
-// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx17,since-cxx11
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98-17,cxx98
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98-17,since-cxx11
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98-17,since-cxx11
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,cxx98-17,since-cxx11
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx17,since-cxx11
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx17,since-cxx11
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx17,since-cxx11
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp
index 9c6c5e00c96d7..ea05e714601fc 100644
--- a/clang/test/CXX/drs/cwg5xx.cpp
+++ b/clang/test/CXX/drs/cwg5xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-23,cxx98-14,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-23,since-cxx17,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-23,since-cxx20,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-23,since-cxx23,since-cxx20,since-cxx17,since-cxx11
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx26,since-cxx23,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-14,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx17,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx23,since-cxx20,since-cxx17,since-cxx11
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx26,since-cxx23,since-cxx20,since-cxx17,since-cxx11
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp
index fa56b8b471ccb..b7b2ebf700375 100644
--- a/clang/test/CXX/drs/cwg6xx.cpp
+++ b/clang/test/CXX/drs/cwg6xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-17,cxx98-14,cxx98
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx11-20,cxx98-17,cxx11-17,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,cxx11-20,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx11
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx11
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-17,cxx98-14,cxx98
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx11-20,cxx98-17,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,cxx11-20,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx11
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx11
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg787.cpp b/clang/test/CXX/drs/cwg787.cpp
index 4b5aeb6487a00..5df769318981a 100644
--- a/clang/test/CXX/drs/cwg787.cpp
+++ b/clang/test/CXX/drs/cwg787.cpp
@@ -1,10 +1,11 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2c %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify
+
// expected-no-diagnostics
// This file intentionally does not end with a newline. CWG787 made this
diff --git a/clang/test/CXX/drs/cwg7xx.cpp b/clang/test/CXX/drs/cwg7xx.cpp
index a0c4c46538847..39fcc53cae2ea 100644
--- a/clang/test/CXX/drs/cwg7xx.cpp
+++ b/clang/test/CXX/drs/cwg7xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98,cxx98-14,cxx98-11
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,cxx98-11,since-cxx11
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-14,since-cxx14,since-cxx11,cxx14
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx17,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98,cxx98-14,cxx98-11
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx98-11,since-cxx11
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,since-cxx14,since-cxx11,cxx14
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx17,since-cxx14,since-cxx11
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
diff --git a/clang/test/CXX/drs/cwg8xx.cpp b/clang/test/CXX/drs/cwg8xx.cpp
index 612b4dff1fe8e..b512411bdf27b 100644
--- a/clang/test/CXX/drs/cwg8xx.cpp
+++ b/clang/test/CXX/drs/cwg8xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-17
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx11
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx11
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx20,since-cxx11
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-17
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx11
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx11
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx11
namespace cwg820 { // cwg820: 2.7
export template <class T> struct B {};
diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp
index 4adeb68330d54..c8fdca3a45c3e 100644
--- a/clang/test/CXX/drs/cwg9xx.cpp
+++ b/clang/test/CXX/drs/cwg9xx.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected
-// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
namespace std {
__extension__ typedef __SIZE_TYPE__ size_t;
>From 79379cbbfb69aed42f9f9d91346ff8d47dfd86a6 Mon Sep 17 00:00:00 2001
From: Pengcheng Wang <wangpengcheng.pp at bytedance.com>
Date: Wed, 18 Mar 2026 18:34:03 +0800
Subject: [PATCH 16/33] [DAG] Add back SelectionDAG::dump() without parameter
(#187001)
Usually `dump()`s are without parameter, so the practice is calling
`XXX::dump()` when debugging.
But we will get an error like below after #161097:
```
error: <user expression 128>:1:10: too few arguments to function call,
expected 1, have 0
1 | DAG.dump()
| ~~~~~~~~ ^
```
So to not surprise users, I added back the `SelectionDAG::dump()`
without parameter.
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 7 ++++++-
llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 2 ++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index b2a9e076fb90e..680c45440521e 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2083,9 +2083,14 @@ class SelectionDAG {
/// function mirrors \c llvm::salvageDebugInfo.
LLVM_ABI void salvageDebugInfo(SDNode &N);
+ /// Dump the textual format of this DAG. Nodes are not sorted.
+ /// Note that we overload it instead of using default value so that it is
+ /// convenient to be called from debuggers.
+ LLVM_ABI void dump() const;
+
/// Dump the textual format of this DAG. Print nodes in sorted orders if \p
/// Sorted is true.
- LLVM_ABI void dump(bool Sorted = false) const;
+ LLVM_ABI void dump(bool Sorted) const;
/// In most cases this function returns the ABI alignment for a given type,
/// except for illegal vector types where the alignment exceeds that of the
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 7161dd299f830..6c9387418ae2e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -1092,6 +1092,8 @@ static void DumpNodes(const SDNode *N, unsigned indent, const SelectionDAG *G) {
N->dump(G);
}
+LLVM_DUMP_METHOD void SelectionDAG::dump() const { dump(false); }
+
LLVM_DUMP_METHOD void SelectionDAG::dump(bool Sorted) const {
dbgs() << "SelectionDAG has " << AllNodes.size() << " nodes:\n";
>From 84c69a975fd7dbbb9dfbc592368f36483876b928 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 18 Mar 2026 11:38:51 +0100
Subject: [PATCH 17/33] [PowerPC] Preserve load output chain in vcmpequb
combine (#187010)
Replace uses of the old load output chain with the new load output
chain. A plain replacement here is fine because the transform verifies
the load is one-use.
Fixes https://github.com/llvm/llvm-project/issues/186549.
---
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 7 ++-
.../CodeGen/PowerPC/load-i128-eq-chain.ll | 47 +++++++++++++++++++
2 files changed, 52 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 1515ff2e13b85..c0ce3ad1625c8 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15768,8 +15768,11 @@ SDValue convertTwoLoadsAndCmpToVCMPEQUB(SelectionDAG &DAG, SDNode *N,
assert(Operand.getOpcode() == ISD::LOAD && "Must be LoadSDNode here.");
auto *LoadNode = cast<LoadSDNode>(Operand);
- return DAG.getLoad(MVT::v16i8, DL, LoadNode->getChain(),
- LoadNode->getBasePtr(), LoadNode->getMemOperand());
+ SDValue NewLoad =
+ DAG.getLoad(MVT::v16i8, DL, LoadNode->getChain(),
+ LoadNode->getBasePtr(), LoadNode->getMemOperand());
+ DAG.ReplaceAllUsesOfValueWith(Operand.getValue(1), NewLoad.getValue(1));
+ return NewLoad;
};
// Following code transforms the DAG
diff --git a/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll b/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
new file mode 100644
index 0000000000000..6fc3e07cb21f5
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=ppc64le-unknown-linux-gnu < %s | FileCheck %s
+
+; Make sure the loads happen after each call, not after both calls.
+define i1 @test() nounwind {
+; CHECK-LABEL: test:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mflr 0
+; CHECK-NEXT: stdu 1, -96(1)
+; CHECK-NEXT: std 0, 112(1)
+; CHECK-NEXT: std 30, 80(1) # 8-byte Folded Spill
+; CHECK-NEXT: li 3, 64
+; CHECK-NEXT: addi 30, 1, 48
+; CHECK-NEXT: stxvd2x 63, 1, 3 # 16-byte Folded Spill
+; CHECK-NEXT: mr 3, 30
+; CHECK-NEXT: bl call
+; CHECK-NEXT: nop
+; CHECK-NEXT: lxvd2x 63, 0, 30
+; CHECK-NEXT: mr 3, 30
+; CHECK-NEXT: bl call
+; CHECK-NEXT: nop
+; CHECK-NEXT: lxvd2x 34, 0, 30
+; CHECK-NEXT: li 4, 64
+; CHECK-NEXT: ld 30, 80(1) # 8-byte Folded Reload
+; CHECK-NEXT: vcmpequb. 2, 31, 2
+; CHECK-NEXT: lxvd2x 63, 1, 4 # 16-byte Folded Reload
+; CHECK-NEXT: mfocrf 3, 2
+; CHECK-NEXT: rlwinm 3, 3, 25, 31, 31
+; CHECK-NEXT: addi 1, 1, 96
+; CHECK-NEXT: ld 0, 16(1)
+; CHECK-NEXT: mtlr 0
+; CHECK-NEXT: blr
+ %a1 = alloca [16 x i8], align 16
+ %a2 = alloca [16 x i8], align 16
+ call void @llvm.lifetime.start.p0(i64 16, ptr %a2)
+ call void @call(ptr %a2)
+ %l1 = load i128, ptr %a2, align 16
+ call void @llvm.lifetime.end.p0(i64 16, ptr %a2)
+ call void @llvm.lifetime.start.p0(i64 16, ptr %a1)
+ call void @call(ptr %a1)
+ %l2 = load i128, ptr %a1, align 16
+ call void @llvm.lifetime.end.p0(i64 16, ptr %a1)
+ %res = icmp eq i128 %l1, %l2
+ ret i1 %res
+}
+
+declare void @call(ptr)
>From 64e5a12990ad6a806b4e737290df569a24e1f757 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Wed, 18 Mar 2026 21:39:21 +1100
Subject: [PATCH 18/33] [orc-rt] Add ShutdownRequested flag to
Service::onDetach. (#187230)
The ShutdownRequested flag indicates to Services whether a shutdown
operation is already pending. Services may use this information to
optimize their book-keeping: either preparing for a (potentially
lengthy) detached state, or for an upcoming shutdown.
Session does not call onDetached yet: That (including setting the
ShutdownRequested argument) will happen in a follow-up patch.
---
orc-rt/include/orc-rt/Service.h | 22 +++++++++++++------
orc-rt/include/orc-rt/SimpleNativeMemoryMap.h | 3 ++-
orc-rt/lib/executor/SimpleNativeMemoryMap.cpp | 3 ++-
orc-rt/unittests/SessionTest.cpp | 6 +++--
.../SimpleNativeMemoryMapSPSCITest.cpp | 2 +-
.../unittests/SimpleNativeMemoryMapTest.cpp | 2 +-
6 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/orc-rt/include/orc-rt/Service.h b/orc-rt/include/orc-rt/Service.h
index 23c3f189ae6a4..172ebe96338f1 100644
--- a/orc-rt/include/orc-rt/Service.h
+++ b/orc-rt/include/orc-rt/Service.h
@@ -28,14 +28,22 @@ class Service {
virtual ~Service();
- /// The onDetach method will be called if the controller disconnects from the
- /// session without shutting the session down.
+ /// The onDetach method will be called when the controller disconnects from
+ /// the session (or if the Session is shut down without a controller ever
+ /// being attached).
///
- /// Since no further requests to the Service will be made, the Service may
- /// discard any book-keeping data-structures that are only needed to serve
- /// ongoing requests. E.g. a JIT memory manager may discard its free-list,
- /// since no further JIT'd allocations will happen.
- virtual void onDetach(OnCompleteFn OnComplete) = 0;
+ /// Once onDetach is called no further requests will be made to the Service
+ /// by the controller. Note that JIT'd code may continue to make requests to
+ /// the service concurrent with a call to onDetach.
+ ///
+ /// If ShutdownRequested is true then a Session shutdown is already pending,
+ /// and will proceed after all Services have been notified of the detach.
+ ///
+ /// onDetach provides an opportunity for Services to release any resources
+ /// that are only required while the Session is attached to the controller.
+ /// It is expected that many Services will implement this operation as a
+ /// no-op.
+ virtual void onDetach(OnCompleteFn OnComplete, bool ShutdownRequested) = 0;
/// The onShutdown operation will be called at the end of the session.
///
diff --git a/orc-rt/include/orc-rt/SimpleNativeMemoryMap.h b/orc-rt/include/orc-rt/SimpleNativeMemoryMap.h
index f54ea17420e70..df8b60260e3bf 100644
--- a/orc-rt/include/orc-rt/SimpleNativeMemoryMap.h
+++ b/orc-rt/include/orc-rt/SimpleNativeMemoryMap.h
@@ -110,7 +110,8 @@ class SimpleNativeMemoryMap : public Service {
void deinitializeMultiple(OnDeinitializeCompleteFn &&OnComplete,
std::vector<void *> Bases);
- void onDetach(Service::OnCompleteFn OnComplete) override;
+ void onDetach(Service::OnCompleteFn OnComplete,
+ bool ShutdownRequested) override;
void onShutdown(Service::OnCompleteFn OnComplete) override;
private:
diff --git a/orc-rt/lib/executor/SimpleNativeMemoryMap.cpp b/orc-rt/lib/executor/SimpleNativeMemoryMap.cpp
index 7bf40367c0d38..c77994e6acb0a 100644
--- a/orc-rt/lib/executor/SimpleNativeMemoryMap.cpp
+++ b/orc-rt/lib/executor/SimpleNativeMemoryMap.cpp
@@ -200,7 +200,8 @@ void SimpleNativeMemoryMap::deinitializeMultiple(
Error::success());
}
-void SimpleNativeMemoryMap::onDetach(Service::OnCompleteFn OnComplete) {
+void SimpleNativeMemoryMap::onDetach(Service::OnCompleteFn OnComplete,
+ bool ShutdownRequested) {
// Detach is a noop for now: we just retain all actions to run at shutdown
// time.
OnComplete();
diff --git a/orc-rt/unittests/SessionTest.cpp b/orc-rt/unittests/SessionTest.cpp
index ce0c77c9af76d..323e7d20ec709 100644
--- a/orc-rt/unittests/SessionTest.cpp
+++ b/orc-rt/unittests/SessionTest.cpp
@@ -40,7 +40,7 @@ class MockService : public Service {
: DetachOpIdx(DetachOpIdx), ShutdownOpIdx(ShutdownOpIdx), OpIdx(OpIdx),
GenResult(std::move(GenResult)) {}
- void onDetach(OnCompleteFn OnComplete) override {
+ void onDetach(OnCompleteFn OnComplete, bool ShutdownRequested) override {
DetachOpIdx = OpIdx++;
GenResult(Op::Detach);
OnComplete();
@@ -63,7 +63,9 @@ class ConfigurableService : public Service {
public:
ConfigurableService(int ConstructorOption) {}
- void onDetach(OnCompleteFn OnComplete) override { OnComplete(); }
+ void onDetach(OnCompleteFn OnComplete, bool ShutdownRequested) override {
+ OnComplete();
+ }
void onShutdown(OnCompleteFn OnComplete) override { OnComplete(); }
diff --git a/orc-rt/unittests/SimpleNativeMemoryMapSPSCITest.cpp b/orc-rt/unittests/SimpleNativeMemoryMapSPSCITest.cpp
index 7398293fb9e43..f5761e2894016 100644
--- a/orc-rt/unittests/SimpleNativeMemoryMapSPSCITest.cpp
+++ b/orc-rt/unittests/SimpleNativeMemoryMapSPSCITest.cpp
@@ -313,7 +313,7 @@ TEST_F(SimpleNativeMemoryMapSPSCITest, ReserveInitializeDetachShutdown) {
EXPECT_EQ(SentinelValue, 0U);
std::future<void> DetachResult;
- SNMM->onDetach(waitFor(DetachResult));
+ SNMM->onDetach(waitFor(DetachResult), /* ShutdownRequested */ false);
DetachResult.get();
EXPECT_EQ(SentinelValue, 0);
diff --git a/orc-rt/unittests/SimpleNativeMemoryMapTest.cpp b/orc-rt/unittests/SimpleNativeMemoryMapTest.cpp
index d42aa0952b251..151237a550f6f 100644
--- a/orc-rt/unittests/SimpleNativeMemoryMapTest.cpp
+++ b/orc-rt/unittests/SimpleNativeMemoryMapTest.cpp
@@ -317,7 +317,7 @@ TEST(SimpleNativeMemoryMapTest, ReserveInitializeDetachShutdown) {
EXPECT_EQ(SentinelValue, 0U);
std::future<void> DetachResult;
- SNMM->onDetach(waitFor(DetachResult));
+ SNMM->onDetach(waitFor(DetachResult), /* ShutdownRequested */ false);
DetachResult.get();
EXPECT_EQ(SentinelValue, 0);
>From fd19099ffc9059824eabd229d72dbd3cbcc717c5 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Wed, 18 Mar 2026 11:49:10 +0100
Subject: [PATCH 19/33] [Frontend/OpenMP][NFC] Drop uses of BranchInst
(#186393)
In OpenMPIRBuilder::EmitOMPInlinedRegion there are two checks w.r.t.
SplitPos, which appear to be always true. I conservatively left the code
as-is.
---
.../llvm/Frontend/OpenMP/OMPIRBuilder.h | 2 +-
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 42 +++---
.../Frontend/OpenMPIRBuilderTest.cpp | 137 ++++++++----------
3 files changed, 77 insertions(+), 104 deletions(-)
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 042c3c75e9cb8..383fd9d94661a 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -4230,7 +4230,7 @@ class CanonicalLoopInfo {
/// eventually branch to the \p Latch block.
BasicBlock *getBody() const {
assert(isValid() && "Requires a valid canonical loop");
- return cast<BranchInst>(Cond->getTerminator())->getSuccessor(0);
+ return cast<CondBrInst>(Cond->getTerminator())->getSuccessor(0);
}
/// Reaching the latch indicates the end of the loop body code. In the
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index a1a25075f3703..d9a8362e79747 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -297,16 +297,14 @@ computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks,
/// the current head of the IR construction).
static void redirectTo(BasicBlock *Source, BasicBlock *Target, DebugLoc DL) {
if (Instruction *Term = Source->getTerminator()) {
- auto *Br = cast<BranchInst>(Term);
- assert(!Br->isConditional() &&
- "BB's terminator must be an unconditional branch (or degenerate)");
- BasicBlock *Succ = Br->getSuccessor(0);
+ auto *Br = cast<UncondBrInst>(Term);
+ BasicBlock *Succ = Br->getSuccessor();
Succ->removePredecessor(Source, /*KeepOneInputPHIs=*/true);
- Br->setSuccessor(0, Target);
+ Br->setSuccessor(Target);
return;
}
- auto *NewBr = BranchInst::Create(Target, Source);
+ auto *NewBr = UncondBrInst::Create(Target, Source);
NewBr->setDebugLoc(DL);
}
@@ -332,7 +330,7 @@ void llvm::spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New,
New->splice(New->begin(), Old, IP.getPoint(), Old->end());
if (CreateBranch) {
- auto *NewBr = BranchInst::Create(New, Old);
+ auto *NewBr = UncondBrInst::Create(New, Old);
NewBr->setDebugLoc(DL);
}
}
@@ -2779,7 +2777,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createSections(
M.getContext(), "omp_section_loop.body.case", CurFn, Continue);
SwitchStmt->addCase(Builder.getInt32(CaseNumber), CaseBB);
Builder.SetInsertPoint(CaseBB);
- BranchInst *CaseEndBr = Builder.CreateBr(Continue);
+ UncondBrInst *CaseEndBr = Builder.CreateBr(Continue);
if (Error Err = SectionCB(InsertPointTy(), {CaseEndBr->getParent(),
CaseEndBr->getIterator()}))
return Err;
@@ -6219,8 +6217,8 @@ OpenMPIRBuilder::applyDynamicWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI,
// Then set the pre-header to jump to the OuterCond
Instruction *Term = PreHeader->getTerminator();
- auto *Br = cast<BranchInst>(Term);
- Br->setSuccessor(0, OuterCond);
+ auto *Br = cast<UncondBrInst>(Term);
+ Br->setSuccessor(OuterCond);
// Modify the inner condition:
// * Use the UpperBound returned from the DynamicNext call.
@@ -6232,7 +6230,7 @@ OpenMPIRBuilder::applyDynamicWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI,
CI->setOperand(1, UpperBound);
// Redirect the inner exit to branch to outer condition.
Instruction *Branch = &Cond->back();
- auto *BI = cast<BranchInst>(Branch);
+ auto *BI = cast<CondBrInst>(Branch);
assert(BI->getSuccessor(1) == Exit);
BI->setSuccessor(1, OuterCond);
@@ -7451,7 +7449,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::EmitOMPInlinedRegion(
// for conditional creation
BasicBlock *EntryBB = Builder.GetInsertBlock();
Instruction *SplitPos = EntryBB->getTerminator();
- if (!isa_and_nonnull<BranchInst>(SplitPos))
+ if (!isa_and_nonnull<UncondBrInst, CondBrInst>(SplitPos))
SplitPos = new UnreachableInst(Builder.getContext(), EntryBB);
BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end");
BasicBlock *FiniBB =
@@ -7482,7 +7480,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::EmitOMPInlinedRegion(
auto merged = MergeBlockIntoPredecessor(ExitBB);
BasicBlock *ExitPredBB = SplitPos->getParent();
auto InsertBB = merged ? ExitPredBB : ExitBB;
- if (!isa_and_nonnull<BranchInst>(SplitPos))
+ if (!isa_and_nonnull<UncondBrInst, CondBrInst>(SplitPos))
SplitPos->eraseFromParent();
Builder.SetInsertPoint(InsertBB);
@@ -7580,7 +7578,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createCopyinClauseBlocks(
// If entry block is terminated, split to preserve the branch to following
// basic block (i.e. OMP.Entry.Next), otherwise, leave everything as is.
- if (isa_and_nonnull<BranchInst>(OMP_Entry->getTerminator())) {
+ if (isa_and_nonnull<CondBrInst>(OMP_Entry->getTerminator())) {
CopyEnd = OMP_Entry->splitBasicBlock(OMP_Entry->getTerminator(),
"copyin.not.master.end");
OMP_Entry->getTerminator()->eraseFromParent();
@@ -12087,13 +12085,13 @@ void CanonicalLoopInfo::assertOK() const {
// Verify standard control-flow we use for OpenMP loops.
assert(Preheader);
- assert(isa<BranchInst>(Preheader->getTerminator()) &&
+ assert(isa<UncondBrInst>(Preheader->getTerminator()) &&
"Preheader must terminate with unconditional branch");
assert(Preheader->getSingleSuccessor() == Header &&
"Preheader must jump to header");
assert(Header);
- assert(isa<BranchInst>(Header->getTerminator()) &&
+ assert(isa<UncondBrInst>(Header->getTerminator()) &&
"Header must terminate with unconditional branch");
assert(Header->getSingleSuccessor() == Cond &&
"Header must jump to exiting block");
@@ -12102,13 +12100,11 @@ void CanonicalLoopInfo::assertOK() const {
assert(Cond->getSinglePredecessor() == Header &&
"Exiting block only reachable from header");
- assert(isa<BranchInst>(Cond->getTerminator()) &&
+ assert(isa<CondBrInst>(Cond->getTerminator()) &&
"Exiting block must terminate with conditional branch");
- assert(size(successors(Cond)) == 2 &&
- "Exiting block must have two successors");
- assert(cast<BranchInst>(Cond->getTerminator())->getSuccessor(0) == Body &&
+ assert(cast<CondBrInst>(Cond->getTerminator())->getSuccessor(0) == Body &&
"Exiting block's first successor jump to the body");
- assert(cast<BranchInst>(Cond->getTerminator())->getSuccessor(1) == Exit &&
+ assert(cast<CondBrInst>(Cond->getTerminator())->getSuccessor(1) == Exit &&
"Exiting block's second successor must exit the loop");
assert(Body);
@@ -12117,7 +12113,7 @@ void CanonicalLoopInfo::assertOK() const {
assert(!isa<PHINode>(Body->front()));
assert(Latch);
- assert(isa<BranchInst>(Latch->getTerminator()) &&
+ assert(isa<UncondBrInst>(Latch->getTerminator()) &&
"Latch must terminate with unconditional branch");
assert(Latch->getSingleSuccessor() == Header && "Latch must jump to header");
// TODO: To support simple redirecting of the end of the body code that has
@@ -12126,7 +12122,7 @@ void CanonicalLoopInfo::assertOK() const {
assert(!isa<PHINode>(Latch->front()));
assert(Exit);
- assert(isa<BranchInst>(Exit->getTerminator()) &&
+ assert(isa<UncondBrInst>(Exit->getTerminator()) &&
"Exit block must terminate with unconditional branch");
assert(Exit->getSingleSuccessor() == After &&
"Exit block must jump to after block");
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index eab4f88c7fbf7..8c591db1ebc6e 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -413,7 +413,7 @@ TEST_F(OpenMPIRBuilderTest, CreateCancel) {
auto FiniCB = [&](InsertPointTy IP) {
ASSERT_NE(IP.getBlock(), nullptr);
ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
- BranchInst::Create(CBB, IP.getBlock());
+ UncondBrInst::Create(CBB, IP.getBlock());
};
OMPBuilder.pushFinalizationCB({FINICB_WRAPPER(FiniCB), OMPD_parallel, true});
@@ -474,7 +474,7 @@ TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
auto FiniCB = [&](InsertPointTy IP) {
ASSERT_NE(IP.getBlock(), nullptr);
ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
- BranchInst::Create(CBB, IP.getBlock());
+ UncondBrInst::Create(CBB, IP.getBlock());
};
OMPBuilder.pushFinalizationCB({FINICB_WRAPPER(FiniCB), OMPD_parallel, true});
@@ -489,8 +489,7 @@ TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
EXPECT_EQ(M->size(), 4U);
EXPECT_EQ(F->size(), 10U);
EXPECT_EQ(BB->size(), 1U);
- ASSERT_TRUE(isa<BranchInst>(BB->getTerminator()));
- ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U);
+ ASSERT_TRUE(isa<CondBrInst>(BB->getTerminator()));
BB = BB->getTerminator()->getSuccessor(0);
EXPECT_EQ(BB->size(), 4U);
@@ -541,7 +540,7 @@ TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
auto FiniCB = [&](InsertPointTy IP) {
ASSERT_NE(IP.getBlock(), nullptr);
ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
- BranchInst::Create(CBB, IP.getBlock());
+ UncondBrInst::Create(CBB, IP.getBlock());
};
OMPBuilder.pushFinalizationCB({FINICB_WRAPPER(FiniCB), OMPD_parallel, true});
@@ -1289,18 +1288,16 @@ TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
for (const User *Usr : FakeDestructor->users()) {
const CallInst *CI = dyn_cast<CallInst>(Usr);
ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
- ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
- ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
+ ASSERT_TRUE(isa<UncondBrInst>(CI->getNextNode()));
if (ExitBB)
ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
else
ExitBB = CI->getNextNode()->getSuccessor(0);
ASSERT_EQ(ExitBB->size(), 1U);
if (!isa<ReturnInst>(ExitBB->front())) {
- ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
- ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
+ ASSERT_TRUE(isa<UncondBrInst>(ExitBB->front()));
ASSERT_TRUE(isa<ReturnInst>(
- cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
+ cast<UncondBrInst>(ExitBB->front()).getSuccessor()->front()));
}
}
}
@@ -1517,7 +1514,7 @@ TEST_F(OpenMPIRBuilderTest, CollapseNestedLoops) {
BasicBlock *LoopNextEnter =
BasicBlock::Create(M->getContext(), "loopnest.enter", F,
Builder.GetInsertBlock()->getNextNode());
- BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
+ UncondBrInst *EnterBr = Builder.CreateBr(LoopNextEnter);
InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
Builder.SetInsertPoint(LoopNextEnter);
@@ -1750,7 +1747,7 @@ TEST_F(OpenMPIRBuilderTest, TileNestedLoopsWithBounds) {
BasicBlock *LoopNextEnter =
BasicBlock::Create(M->getContext(), "loopnest.enter", F,
Builder.GetInsertBlock()->getNextNode());
- BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
+ UncondBrInst *EnterBr = Builder.CreateBr(LoopNextEnter);
InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
InsertPointTy LoopIP{LoopNextEnter, LoopNextEnter->begin()};
@@ -2243,7 +2240,7 @@ TEST_F(OpenMPIRBuilderTest, ApplySimdIf) {
// Check for if condition
BasicBlock *LoopBody = CLI->getBody();
- BranchInst *IfCond = cast<BranchInst>(LoopBody->getTerminator());
+ CondBrInst *IfCond = cast<CondBrInst>(LoopBody->getTerminator());
EXPECT_EQ(IfCond->getCondition(), IfCmp);
BasicBlock *TrueBranch = IfCond->getSuccessor(0);
BasicBlock *FalseBranch = IfCond->getSuccessor(1)->getUniqueSuccessor();
@@ -2897,9 +2894,8 @@ TEST_F(OpenMPIRBuilderTest, MasterDirective) {
Builder.restoreIP(AfterIP);
Value *EntryBBTI = EntryBB->getTerminator();
EXPECT_NE(EntryBBTI, nullptr);
- EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
- BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
- EXPECT_TRUE(EntryBr->isConditional());
+ EXPECT_TRUE(isa<CondBrInst>(EntryBBTI));
+ CondBrInst *EntryBr = cast<CondBrInst>(EntryBB->getTerminator());
EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
BasicBlock *FinalizeBB = ThenBB->getUniqueSuccessor();
BasicBlock *ExitBB = FinalizeBB->getUniqueSuccessor();
@@ -2980,9 +2976,8 @@ TEST_F(OpenMPIRBuilderTest, MaskedDirective) {
Builder.restoreIP(AfterIP);
Value *EntryBBTI = EntryBB->getTerminator();
EXPECT_NE(EntryBBTI, nullptr);
- EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
- BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
- EXPECT_TRUE(EntryBr->isConditional());
+ EXPECT_TRUE(isa<CondBrInst>(EntryBBTI));
+ CondBrInst *EntryBr = cast<CondBrInst>(EntryBB->getTerminator());
EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
BasicBlock *FinalizeBB = ThenBB->getUniqueSuccessor();
BasicBlock *ExitBB = FinalizeBB->getUniqueSuccessor();
@@ -3425,10 +3420,9 @@ TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
OMPBuilder.createCopyinClauseBlocks(Builder.saveIP(), MasterAddress,
PrivAddress, Int32, /*BranchtoEnd*/ true);
- BranchInst *EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator());
+ CondBrInst *EntryBr = dyn_cast_or_null<CondBrInst>(EntryBB->getTerminator());
EXPECT_NE(EntryBr, nullptr);
- EXPECT_TRUE(EntryBr->isConditional());
BasicBlock *NotMasterBB = EntryBr->getSuccessor(0);
BasicBlock *CopyinEnd = EntryBr->getSuccessor(1);
@@ -3438,11 +3432,10 @@ TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
EXPECT_NE(NotMasterBB, nullptr);
EXPECT_NE(CopyinEnd, nullptr);
- BranchInst *NotMasterBr =
- dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator());
+ UncondBrInst *NotMasterBr =
+ dyn_cast_or_null<UncondBrInst>(NotMasterBB->getTerminator());
EXPECT_NE(NotMasterBr, nullptr);
- EXPECT_FALSE(NotMasterBr->isConditional());
- EXPECT_EQ(CopyinEnd, NotMasterBr->getSuccessor(0));
+ EXPECT_EQ(CopyinEnd, NotMasterBr->getSuccessor());
}
TEST_F(OpenMPIRBuilderTest, SingleDirective) {
@@ -3495,9 +3488,8 @@ TEST_F(OpenMPIRBuilderTest, SingleDirective) {
Builder.restoreIP(AfterIP);
Value *EntryBBTI = EntryBB->getTerminator();
EXPECT_NE(EntryBBTI, nullptr);
- EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
- BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
- EXPECT_TRUE(EntryBr->isConditional());
+ EXPECT_TRUE(isa<CondBrInst>(EntryBBTI));
+ CondBrInst *EntryBr = cast<CondBrInst>(EntryBB->getTerminator());
EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
BasicBlock *FinalizeBB = ThenBB->getUniqueSuccessor();
BasicBlock *ExitBB = FinalizeBB->getUniqueSuccessor();
@@ -3589,9 +3581,8 @@ TEST_F(OpenMPIRBuilderTest, SingleDirectiveNowait) {
Builder.restoreIP(AfterIP);
Value *EntryBBTI = EntryBB->getTerminator();
EXPECT_NE(EntryBBTI, nullptr);
- EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
- BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
- EXPECT_TRUE(EntryBr->isConditional());
+ EXPECT_TRUE(isa<CondBrInst>(EntryBBTI));
+ CondBrInst *EntryBr = cast<CondBrInst>(EntryBB->getTerminator());
EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
BasicBlock *FinalizeBB = ThenBB->getUniqueSuccessor();
BasicBlock *ExitBB = FinalizeBB->getUniqueSuccessor();
@@ -3713,9 +3704,8 @@ TEST_F(OpenMPIRBuilderTest, SingleDirectiveCopyPrivate) {
Builder.restoreIP(AfterIP);
Value *EntryBBTI = EntryBB->getTerminator();
EXPECT_NE(EntryBBTI, nullptr);
- EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
- BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
- EXPECT_TRUE(EntryBr->isConditional());
+ EXPECT_TRUE(isa<CondBrInst>(EntryBBTI));
+ CondBrInst *EntryBr = cast<CondBrInst>(EntryBB->getTerminator());
EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
BasicBlock *FinalizeBB = ThenBB->getUniqueSuccessor();
BasicBlock *ExitBB = FinalizeBB->getUniqueSuccessor();
@@ -3754,10 +3744,9 @@ TEST_F(OpenMPIRBuilderTest, SingleDirectiveCopyPrivate) {
EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
// br ExitBB
- auto *ExitBBBI = FinalizeBBI.next<BranchInst>();
+ auto *ExitBBBI = FinalizeBBI.next<UncondBrInst>();
EXPECT_NE(ExitBBBI, nullptr);
- EXPECT_TRUE(ExitBBBI->isUnconditional());
- EXPECT_EQ(ExitBBBI->getOperand(0), ExitBB);
+ EXPECT_EQ(ExitBBBI->getSuccessor(), ExitBB);
EXPECT_FALSE(FinalizeBBI.hasNext());
// check ExitBB
@@ -3993,10 +3982,9 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicUpdate) {
IsXLHSInRHSPart));
Builder.restoreIP(AfterIP);
BasicBlock *ContBB = EntryBB->getSingleSuccessor();
- BranchInst *ContTI = dyn_cast<BranchInst>(ContBB->getTerminator());
+ CondBrInst *ContTI = dyn_cast<CondBrInst>(ContBB->getTerminator());
EXPECT_NE(ContTI, nullptr);
BasicBlock *EndBB = ContTI->getSuccessor(0);
- EXPECT_TRUE(ContTI->isConditional());
EXPECT_EQ(ContTI->getSuccessor(1), ContBB);
EXPECT_NE(EndBB, nullptr);
@@ -4063,10 +4051,9 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicUpdateFloat) {
IsXLHSInRHSPart));
Builder.restoreIP(AfterIP);
BasicBlock *ContBB = EntryBB->getSingleSuccessor();
- BranchInst *ContTI = dyn_cast<BranchInst>(ContBB->getTerminator());
+ CondBrInst *ContTI = dyn_cast<CondBrInst>(ContBB->getTerminator());
EXPECT_NE(ContTI, nullptr);
BasicBlock *EndBB = ContTI->getSuccessor(0);
- EXPECT_TRUE(ContTI->isConditional());
EXPECT_EQ(ContTI->getSuccessor(1), ContBB);
EXPECT_NE(EndBB, nullptr);
@@ -4132,10 +4119,9 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicUpdateIntr) {
IsXLHSInRHSPart));
Builder.restoreIP(AfterIP);
BasicBlock *ContBB = EntryBB->getSingleSuccessor();
- BranchInst *ContTI = dyn_cast<BranchInst>(ContBB->getTerminator());
+ CondBrInst *ContTI = dyn_cast<CondBrInst>(ContBB->getTerminator());
EXPECT_NE(ContTI, nullptr);
BasicBlock *EndBB = ContTI->getSuccessor(0);
- EXPECT_TRUE(ContTI->isConditional());
EXPECT_EQ(ContTI->getSuccessor(1), ContBB);
EXPECT_NE(EndBB, nullptr);
@@ -4418,9 +4404,8 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicCompareCapture) {
EXPECT_NE(ExtVal5, nullptr);
EXPECT_EQ(ExtVal5->getAggregateOperand(), CmpXchg3);
EXPECT_EQ(ExtVal5->getIndices(), ArrayRef<unsigned int>(1U));
- BranchInst *Br1 = dyn_cast<BranchInst>(ExtVal5->getNextNode());
+ CondBrInst *Br1 = dyn_cast<CondBrInst>(ExtVal5->getNextNode());
EXPECT_NE(Br1, nullptr);
- EXPECT_EQ(Br1->isConditional(), true);
EXPECT_EQ(Br1->getCondition(), ExtVal5);
EXPECT_EQ(Br1->getSuccessor(0), Exit1);
EXPECT_EQ(Br1->getSuccessor(1), Cont1);
@@ -4429,10 +4414,9 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicCompareCapture) {
EXPECT_NE(Store3, nullptr);
EXPECT_EQ(Store3->getPointerOperand(), VVal);
EXPECT_EQ(Store3->getValueOperand(), ExtVal4);
- BranchInst *Br2 = dyn_cast<BranchInst>(Store3->getNextNode());
+ UncondBrInst *Br2 = dyn_cast<UncondBrInst>(Store3->getNextNode());
EXPECT_NE(Br2, nullptr);
- EXPECT_EQ(Br2->isUnconditional(), true);
- EXPECT_EQ(Br2->getSuccessor(0), Exit1);
+ EXPECT_EQ(Br2->getSuccessor(), Exit1);
AtomicCmpXchgInst *CmpXchg4 = dyn_cast<AtomicCmpXchgInst>(&Exit1->front());
EXPECT_NE(CmpXchg4, nullptr);
@@ -4468,9 +4452,8 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicCompareCapture) {
EXPECT_NE(ExtVal8, nullptr);
EXPECT_EQ(ExtVal8->getAggregateOperand(), CmpXchg5);
EXPECT_EQ(ExtVal8->getIndices(), ArrayRef<unsigned int>(1U));
- BranchInst *Br3 = dyn_cast<BranchInst>(ExtVal8->getNextNode());
+ CondBrInst *Br3 = dyn_cast<CondBrInst>(ExtVal8->getNextNode());
EXPECT_NE(Br3, nullptr);
- EXPECT_EQ(Br3->isConditional(), true);
EXPECT_EQ(Br3->getCondition(), ExtVal8);
EXPECT_EQ(Br3->getSuccessor(0), Exit2);
EXPECT_EQ(Br3->getSuccessor(1), Cont2);
@@ -4479,9 +4462,8 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicCompareCapture) {
EXPECT_NE(Store5, nullptr);
EXPECT_EQ(Store5->getPointerOperand(), VVal);
EXPECT_EQ(Store5->getValueOperand(), ExtVal7);
- BranchInst *Br4 = dyn_cast<BranchInst>(Store5->getNextNode());
+ UncondBrInst *Br4 = dyn_cast<UncondBrInst>(Store5->getNextNode());
EXPECT_NE(Br4, nullptr);
- EXPECT_EQ(Br4->isUnconditional(), true);
EXPECT_EQ(Br4->getSuccessor(0), Exit2);
ExtractValueInst *ExtVal9 = dyn_cast<ExtractValueInst>(&Exit2->front());
@@ -4732,14 +4714,13 @@ TEST_F(OpenMPIRBuilderTest, CreateTeamsWithThreadLimit) {
EXPECT_EQ(PushNumTeamsCallInst->getArgOperand(4), &*F->arg_begin());
// Verifying that the next instruction to execute is kmpc_fork_teams
- BranchInst *BrInst =
- dyn_cast<BranchInst>(PushNumTeamsCallInst->getNextNode());
+ UncondBrInst *BrInst =
+ dyn_cast<UncondBrInst>(PushNumTeamsCallInst->getNextNode());
ASSERT_NE(BrInst, nullptr);
- ASSERT_EQ(BrInst->getNumSuccessors(), 1U);
BasicBlock::iterator NextInstruction =
BrInst->getSuccessor(0)->getFirstNonPHIOrDbgOrLifetime();
CallInst *ForkTeamsCI = nullptr;
- if (NextInstruction != BrInst->getSuccessor(0)->end())
+ if (NextInstruction != BrInst->getSuccessor()->end())
ForkTeamsCI = dyn_cast_if_present<CallInst>(NextInstruction);
ASSERT_NE(ForkTeamsCI, nullptr);
EXPECT_EQ(ForkTeamsCI->getCalledFunction(),
@@ -4789,14 +4770,13 @@ TEST_F(OpenMPIRBuilderTest, CreateTeamsWithNumTeamsUpper) {
EXPECT_EQ(PushNumTeamsCallInst->getArgOperand(4), Builder.getInt32(0));
// Verifying that the next instruction to execute is kmpc_fork_teams
- BranchInst *BrInst =
- dyn_cast<BranchInst>(PushNumTeamsCallInst->getNextNode());
+ UncondBrInst *BrInst =
+ dyn_cast<UncondBrInst>(PushNumTeamsCallInst->getNextNode());
ASSERT_NE(BrInst, nullptr);
- ASSERT_EQ(BrInst->getNumSuccessors(), 1U);
BasicBlock::iterator NextInstruction =
- BrInst->getSuccessor(0)->getFirstNonPHIOrDbgOrLifetime();
+ BrInst->getSuccessor()->getFirstNonPHIOrDbgOrLifetime();
CallInst *ForkTeamsCI = nullptr;
- if (NextInstruction != BrInst->getSuccessor(0)->end())
+ if (NextInstruction != BrInst->getSuccessor()->end())
ForkTeamsCI = dyn_cast_if_present<CallInst>(NextInstruction);
ASSERT_NE(ForkTeamsCI, nullptr);
EXPECT_EQ(ForkTeamsCI->getCalledFunction(),
@@ -4849,14 +4829,13 @@ TEST_F(OpenMPIRBuilderTest, CreateTeamsWithNumTeamsBoth) {
EXPECT_EQ(PushNumTeamsCallInst->getArgOperand(4), Builder.getInt32(0));
// Verifying that the next instruction to execute is kmpc_fork_teams
- BranchInst *BrInst =
- dyn_cast<BranchInst>(PushNumTeamsCallInst->getNextNode());
+ UncondBrInst *BrInst =
+ dyn_cast<UncondBrInst>(PushNumTeamsCallInst->getNextNode());
ASSERT_NE(BrInst, nullptr);
- ASSERT_EQ(BrInst->getNumSuccessors(), 1U);
BasicBlock::iterator NextInstruction =
- BrInst->getSuccessor(0)->getFirstNonPHIOrDbgOrLifetime();
+ BrInst->getSuccessor()->getFirstNonPHIOrDbgOrLifetime();
CallInst *ForkTeamsCI = nullptr;
- if (NextInstruction != BrInst->getSuccessor(0)->end())
+ if (NextInstruction != BrInst->getSuccessor()->end())
ForkTeamsCI = dyn_cast_if_present<CallInst>(NextInstruction);
ASSERT_NE(ForkTeamsCI, nullptr);
EXPECT_EQ(ForkTeamsCI->getCalledFunction(),
@@ -4915,14 +4894,13 @@ TEST_F(OpenMPIRBuilderTest, CreateTeamsWithNumTeamsAndThreadLimit) {
EXPECT_EQ(PushNumTeamsCallInst->getArgOperand(4), ThreadLimit);
// Verifying that the next instruction to execute is kmpc_fork_teams
- BranchInst *BrInst =
- dyn_cast<BranchInst>(PushNumTeamsCallInst->getNextNode());
+ UncondBrInst *BrInst =
+ dyn_cast<UncondBrInst>(PushNumTeamsCallInst->getNextNode());
ASSERT_NE(BrInst, nullptr);
- ASSERT_EQ(BrInst->getNumSuccessors(), 1U);
BasicBlock::iterator NextInstruction =
- BrInst->getSuccessor(0)->getFirstNonPHIOrDbgOrLifetime();
+ BrInst->getSuccessor()->getFirstNonPHIOrDbgOrLifetime();
CallInst *ForkTeamsCI = nullptr;
- if (NextInstruction != BrInst->getSuccessor(0)->end())
+ if (NextInstruction != BrInst->getSuccessor()->end())
ForkTeamsCI = dyn_cast_if_present<CallInst>(NextInstruction);
ASSERT_NE(ForkTeamsCI, nullptr);
EXPECT_EQ(ForkTeamsCI->getCalledFunction(),
@@ -6491,8 +6469,8 @@ TEST_F(OpenMPIRBuilderTest, TargetRegion) {
// Check the kernel launch sequence
auto Iter = F->getEntryBlock().rbegin();
- EXPECT_TRUE(isa<BranchInst>(&*(Iter)));
- BranchInst *Branch = dyn_cast<BranchInst>(&*(Iter));
+ EXPECT_TRUE(isa<CondBrInst>(&*(Iter)));
+ CondBrInst *Branch = dyn_cast<CondBrInst>(&*(Iter));
EXPECT_TRUE(isa<CmpInst>(&*(++Iter)));
EXPECT_TRUE(isa<CallInst>(&*(++Iter)));
CallInst *Call = dyn_cast<CallInst>(&*(Iter));
@@ -6726,7 +6704,7 @@ TEST_F(OpenMPIRBuilderTest, TargetRegionDevice) {
EXPECT_TRUE(isa<LoadInst>(Load2));
auto *OutlinedBlockBr = Load2->getNextNode();
- EXPECT_TRUE(isa<BranchInst>(OutlinedBlockBr));
+ EXPECT_TRUE(isa<UncondBrInst>(OutlinedBlockBr));
auto *OutlinedBlock = OutlinedBlockBr->getSuccessor(0);
EXPECT_EQ(OutlinedBlock->getName(), "outlined.body");
@@ -6827,8 +6805,8 @@ TEST_F(OpenMPIRBuilderTest, TargetRegionSPMD) {
// Check the kernel launch sequence
auto Iter = F->getEntryBlock().rbegin();
- EXPECT_TRUE(isa<BranchInst>(&*(Iter)));
- BranchInst *Branch = dyn_cast<BranchInst>(&*(Iter));
+ EXPECT_TRUE(isa<CondBrInst>(&*(Iter)));
+ CondBrInst *Branch = dyn_cast<CondBrInst>(&*(Iter));
EXPECT_TRUE(isa<CmpInst>(&*(++Iter)));
EXPECT_TRUE(isa<CallInst>(&*(++Iter)));
CallInst *Call = dyn_cast<CallInst>(&*(Iter));
@@ -7116,7 +7094,7 @@ TEST_F(OpenMPIRBuilderTest, ConstantAllocaRaise) {
EXPECT_TRUE(isa<LoadInst>(Load1));
auto *OutlinedBlockBr = Load1->getNextNode();
- EXPECT_TRUE(isa<BranchInst>(OutlinedBlockBr));
+ EXPECT_TRUE(isa<UncondBrInst>(OutlinedBlockBr));
auto *OutlinedBlock = OutlinedBlockBr->getSuccessor(0);
EXPECT_EQ(OutlinedBlock->getName(), "outlined.body");
@@ -7517,10 +7495,9 @@ TEST_F(OpenMPIRBuilderTest, CreateTaskIfCondition) {
ASSERT_NE(TaskAllocCall, nullptr);
// Check the branching is based on the if condition argument.
- BranchInst *IfConditionBranchInst =
- dyn_cast<BranchInst>(TaskAllocCall->getParent()->getTerminator());
+ CondBrInst *IfConditionBranchInst =
+ dyn_cast<CondBrInst>(TaskAllocCall->getParent()->getTerminator());
ASSERT_NE(IfConditionBranchInst, nullptr);
- ASSERT_TRUE(IfConditionBranchInst->isConditional());
EXPECT_EQ(IfConditionBranchInst->getCondition(), IfCondition);
// Check that the `__kmpc_omp_task` executes only in the then branch.
>From b6beda0382f3479545cd3ca5b7f24c9fded78245 Mon Sep 17 00:00:00 2001
From: lonely eagle <2020382038 at qq.com>
Date: Wed, 18 Mar 2026 18:51:52 +0800
Subject: [PATCH 20/33] [mlir][reducer] Add eraseAllOpsInRegion function to
reduction-tree pass (#185892)
Added logic to erase all operations within a region. This addresses
scenarios where the test script always returns 1 (interesting), in which
case the simplest output from mlir-reduce should be an empty ModuleOp.
---
mlir/lib/Reducer/ReductionTreePass.cpp | 50 ++++++++++++++++++++++++--
mlir/test/mlir-reduce/simple-test.mlir | 8 ++++-
2 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/mlir/lib/Reducer/ReductionTreePass.cpp b/mlir/lib/Reducer/ReductionTreePass.cpp
index 1e00ed645f71e..83497143d9669 100644
--- a/mlir/lib/Reducer/ReductionTreePass.cpp
+++ b/mlir/lib/Reducer/ReductionTreePass.cpp
@@ -145,19 +145,63 @@ static LogicalResult findOptimal(ModuleOp module, Region ®ion,
return success();
}
+/// This function attempts to erase all operations within the region currently
+/// being processed.
+static LogicalResult eraseAllOpsInRegion(ModuleOp module, Region ®ion,
+ const Tester &test) {
+ std::pair<Tester::Interestingness, size_t> initStatus =
+ test.isInteresting(module);
+
+ // While exploring the reduction tree, we always branch from an interesting
+ // node. Thus the root node must be interesting.
+ if (initStatus.first != Tester::Interestingness::True)
+ return module.emitWarning() << "uninterested module will not be reduced";
+ llvm::SpecificBumpPtrAllocator<ReductionNode> allocator;
+
+ // Setting the ranges to {{0, 0}} will result in the deletion of all ops
+ // within the region.
+ std::vector<ReductionNode::Range> ranges{{0, 0}};
+
+ // We allocate memory on the stack, and the 'allocator' is only used to
+ // construct the 'root node'. Since we won't be constructing any child nodes
+ // for emptyRegionNode, it is only used within the current scope.
+ ReductionNode emptyRegionNode(nullptr, ranges, allocator);
+ ReductionNode *root = &emptyRegionNode;
+
+ // Create a copy of the current IR.
+ if (failed(root->initialize(module, region)))
+ llvm_unreachable("unexpected initialization failure");
+
+ // Erase all operations within the corresponding region of the clone.
+ applyPatterns(root->getRegion(), {}, root->getRanges(), true);
+ root->update(test.isInteresting(root->getModule()));
+ if (root->isInteresting() == Tester::Interestingness::True) {
+ // If we can successfully remove all ops in the region, we apply the same
+ // transformation to the original IR and return success.
+ applyPatterns(region, {}, root->getRanges(), true);
+ return success();
+ }
+ return failure();
+}
+
template <typename IteratorType>
static LogicalResult findOptimal(ModuleOp module, Region ®ion,
const FrozenRewritePatternSet &patterns,
const Tester &test) {
- // We separate the reduction process into 2 steps, the first one is to erase
+ // We separate the reduction process into 3 steps, the first one is to erase
// redundant operations and the second one is to apply the reducer patterns.
- // In the first phase, we don't apply any patterns so that we only select the
+ // In the first phase, we attempt to erase all operations within the entire
+ // region.
+ if (succeeded(eraseAllOpsInRegion(module, region, test)))
+ return success();
+
+ // In the second phase, we don't apply any patterns so that we only select the
// range of operations to keep to the module stay interesting.
if (failed(findOptimal<IteratorType>(module, region, /*patterns=*/{}, test,
/*eraseOpNotInRange=*/true)))
return failure();
- // In the second phase, we suppose that no operation is redundant, so we try
+ // In the third phase, we suppose that no operation is redundant, so we try
// to rewrite the operation into simpler form.
return findOptimal<IteratorType>(module, region, patterns, test,
/*eraseOpNotInRange=*/false);
diff --git a/mlir/test/mlir-reduce/simple-test.mlir b/mlir/test/mlir-reduce/simple-test.mlir
index 1cc414946a592..b50c39590bb92 100644
--- a/mlir/test/mlir-reduce/simple-test.mlir
+++ b/mlir/test/mlir-reduce/simple-test.mlir
@@ -1,5 +1,8 @@
// UNSUPPORTED: system-windows
-// RUN: mlir-reduce %s -reduction-tree='traversal-mode=0 test=%S/test.sh'
+// RUN: mlir-reduce %s -reduction-tree='traversal-mode=0 test=%S/test.sh' | FileCheck %s
+
+// Since the test.sh always returns 1 (interesting),
+// all operations within the ModuleOp should be erased.
func.func @simple1(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
cf.cond_br %arg0, ^bb1, ^bb2
@@ -11,3 +14,6 @@ func.func @simple1(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
^bb3(%1: memref<2xf32>):
return
}
+
+// CHECK: module {
+// CHECK: }
>From ad918c53e74183dcfa1e071117cd72a99c343235 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Wed, 18 Mar 2026 21:59:09 +1100
Subject: [PATCH 21/33] [orc-rt] Rename Session
setController/detachFromController. NFC. (#187235)
These methods are renamed to attach and detach for simplicity.
---
orc-rt/include/orc-rt/Session.h | 4 ++--
orc-rt/lib/executor/Session.cpp | 6 +++---
orc-rt/unittests/SessionTest.cpp | 10 +++++-----
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/orc-rt/include/orc-rt/Session.h b/orc-rt/include/orc-rt/Session.h
index 1c45eac01ac0a..9d64afaee8f25 100644
--- a/orc-rt/include/orc-rt/Session.h
+++ b/orc-rt/include/orc-rt/Session.h
@@ -166,10 +166,10 @@ class Session {
}
/// Set the ControllerAccess object.
- void setController(std::shared_ptr<ControllerAccess> CA);
+ void attach(std::shared_ptr<ControllerAccess> CA);
/// Disconnect the ControllerAccess object.
- void detachFromController();
+ void detach();
void callController(OnCallHandlerCompleteFn OnComplete, HandlerTag T,
WrapperFunctionBuffer ArgBytes) {
diff --git a/orc-rt/lib/executor/Session.cpp b/orc-rt/lib/executor/Session.cpp
index ef59565ea5344..67033003326f5 100644
--- a/orc-rt/lib/executor/Session.cpp
+++ b/orc-rt/lib/executor/Session.cpp
@@ -28,7 +28,7 @@ void Session::shutdown(OnShutdownCompleteFn OnShutdownComplete) {
assert(OnShutdownComplete && "OnShutdownComplete must be set");
// Safe to call concurrently / redundantly.
- detachFromController();
+ detach();
{
std::scoped_lock<std::mutex> Lock(M);
@@ -69,7 +69,7 @@ void Session::waitForShutdown() {
F.get();
}
-void Session::setController(std::shared_ptr<ControllerAccess> CA) {
+void Session::attach(std::shared_ptr<ControllerAccess> CA) {
assert(CA && "Cannot attach null controller");
std::scoped_lock<std::mutex> Lock(M);
assert(!this->CA && "Cannot re-attach controller");
@@ -77,7 +77,7 @@ void Session::setController(std::shared_ptr<ControllerAccess> CA) {
this->CA = std::move(CA);
}
-void Session::detachFromController() {
+void Session::detach() {
if (auto TmpCA = CA) {
TmpCA->doDisconnect();
CA = nullptr;
diff --git a/orc-rt/unittests/SessionTest.cpp b/orc-rt/unittests/SessionTest.cpp
index 323e7d20ec709..f131ccb61c2a2 100644
--- a/orc-rt/unittests/SessionTest.cpp
+++ b/orc-rt/unittests/SessionTest.cpp
@@ -393,7 +393,7 @@ TEST(ControllerAccessTest, Basics) {
Session S(mockExecutorProcessInfo(),
std::make_unique<EnqueueingDispatcher>(Tasks), noErrors);
auto CA = std::make_shared<MockControllerAccess>(S);
- S.setController(CA);
+ S.attach(CA);
EnqueueingDispatcher::runTasksFromFront(Tasks);
@@ -416,7 +416,7 @@ TEST(ControllerAccessTest, ValidCallToController) {
Session S(mockExecutorProcessInfo(),
std::make_unique<EnqueueingDispatcher>(Tasks), noErrors);
auto CA = std::make_shared<MockControllerAccess>(S);
- S.setController(CA);
+ S.attach(CA);
int32_t Result = 0;
SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(
@@ -456,9 +456,9 @@ TEST(ControllerAccessTest, CallToControllerAfterDetach) {
Session S(mockExecutorProcessInfo(),
std::make_unique<EnqueueingDispatcher>(Tasks), noErrors);
auto CA = std::make_shared<MockControllerAccess>(S);
- S.setController(CA);
+ S.attach(CA);
- S.detachFromController();
+ S.detach();
Error Err = Error::success();
SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(
@@ -480,7 +480,7 @@ TEST(ControllerAccessTest, CallFromController) {
Session S(mockExecutorProcessInfo(),
std::make_unique<EnqueueingDispatcher>(Tasks), noErrors);
auto CA = std::make_shared<MockControllerAccess>(S);
- S.setController(CA);
+ S.attach(CA);
int32_t Result = 0;
SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(
>From c2d54686b53e1c3c98b4293f3d2fcf3fded7b9e8 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 18 Mar 2026 11:08:09 +0000
Subject: [PATCH 22/33] [LV] Add test for diff checks with ptrtoint subtract.
(NFC)
Adds extra test coverage for
https://github.com/llvm/llvm-project/pull/180244.
---
.../runtime-checks-difference.ll | 132 ++++++++++++++++++
1 file changed, 132 insertions(+)
diff --git a/llvm/test/Transforms/LoopVectorize/runtime-checks-difference.ll b/llvm/test/Transforms/LoopVectorize/runtime-checks-difference.ll
index 1ac6fa441a09e..16afd3044d180 100644
--- a/llvm/test/Transforms/LoopVectorize/runtime-checks-difference.ll
+++ b/llvm/test/Transforms/LoopVectorize/runtime-checks-difference.ll
@@ -489,3 +489,135 @@ loop:
exit:
ret void
}
+
+define void @diff_check_via_i32_ptrarith(ptr %origin, ptr %dst, ptr %base, i32 %d, i32 %n) {
+; CHECK-LABEL: define void @diff_check_via_i32_ptrarith(
+; CHECK-SAME: ptr [[ORIGIN:%.*]], ptr [[DST:%.*]], ptr [[BASE:%.*]], i32 [[D:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[BASE1:%.*]] = ptrtoaddr ptr [[BASE]] to i64
+; CHECK-NEXT: [[RHS:%.*]] = ptrtoint ptr [[ORIGIN]] to i64
+; CHECK-NEXT: [[LHS:%.*]] = ptrtoint ptr [[DST]] to i64
+; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[LHS]], [[RHS]]
+; CHECK-NEXT: [[DIFF_I32:%.*]] = trunc i64 [[DIFF]] to i32
+; CHECK-NEXT: [[OP:%.*]] = sub nuw nsw i32 [[D]], [[DIFF_I32]]
+; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[OP]] to i64
+; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE]], i64 [[IDX_EXT]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[OP]], [[N]]
+; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP_PH:.*]], [[EXIT:label %.*]]
+; CHECK: [[LOOP_PH]]:
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[RHS]] to i32
+; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], -1
+; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[LHS]] to i32
+; CHECK-NEXT: [[TMP4:%.*]] = sub i32 [[TMP2]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
+; CHECK-NEXT: [[TMP6:%.*]] = add nuw nsw i64 [[TMP5]], 1
+; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP6]], 4
+; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]
+; CHECK: [[VECTOR_MEMCHECK]]:
+; CHECK-NEXT: [[TMP7:%.*]] = trunc i64 [[RHS]] to i32
+; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[D]], [[TMP7]]
+; CHECK-NEXT: [[TMP9:%.*]] = trunc i64 [[LHS]] to i32
+; CHECK-NEXT: [[TMP10:%.*]] = sub i32 [[TMP8]], [[TMP9]]
+; CHECK-NEXT: [[TMP11:%.*]] = zext i32 [[TMP10]] to i64
+; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[BASE1]], [[TMP11]]
+; CHECK-NEXT: [[TMP13:%.*]] = sub i64 [[LHS]], [[TMP12]]
+; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP13]], 4
+; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]
+;
+entry:
+ %rhs = ptrtoint ptr %origin to i64
+ %lhs = ptrtoint ptr %dst to i64
+ %diff = sub i64 %lhs, %rhs
+ %diff.i32 = trunc i64 %diff to i32
+ %op = sub nuw nsw i32 %d, %diff.i32
+ %idx.ext = zext i32 %op to i64
+ %src = getelementptr inbounds nuw i8, ptr %base, i64 %idx.ext
+ %cmp = icmp ult i32 %op, %n
+ br i1 %cmp, label %loop.ph, label %exit
+
+loop.ph:
+ br label %loop
+
+loop:
+ %dst.phi = phi ptr [ %dst.next, %loop ], [ %dst, %loop.ph ]
+ %src.phi = phi ptr [ %src.next, %loop ], [ %src, %loop.ph ]
+ %iv = phi i32 [ %iv.dec, %loop ], [ %op, %loop.ph ]
+ %src.next = getelementptr inbounds nuw i8, ptr %src.phi, i64 1
+ %val = load i8, ptr %src.phi, align 1
+ %dst.next = getelementptr inbounds nuw i8, ptr %dst.phi, i64 1
+ store i8 %val, ptr %dst.phi, align 1
+ %iv.dec = add i32 %iv, -1
+ %done = icmp eq i32 %iv.dec, 0
+ br i1 %done, label %exit, label %loop, !llvm.loop !0
+
+exit:
+ ret void
+}
+
+define void @phi_of_ptrtoint_diff_check(ptr %base, ptr %end, i64 %n, i1 %cond) {
+; CHECK-LABEL: define void @phi_of_ptrtoint_diff_check(
+; CHECK-SAME: ptr [[BASE:%.*]], ptr [[END:%.*]], i64 [[N:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint ptr [[END]] to i64
+; CHECK-NEXT: [[EXT:%.*]] = getelementptr inbounds nuw i8, ptr [[END]], i64 [[N]]
+; CHECK-NEXT: [[EXT_INT:%.*]] = ptrtoint ptr [[EXT]] to i64
+; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[MERGE:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: br label %[[MERGE]]
+; CHECK: [[MERGE]]:
+; CHECK-NEXT: [[DST_INT:%.*]] = phi i64 [ [[EXT_INT]], %[[IF_THEN]] ], [ [[END_INT]], %[[ENTRY]] ]
+; CHECK-NEXT: [[DST_PTR:%.*]] = phi ptr [ [[EXT]], %[[IF_THEN]] ], [ [[END]], %[[ENTRY]] ]
+; CHECK-NEXT: [[DST_PTR1:%.*]] = ptrtoaddr ptr [[DST_PTR]] to i64
+; CHECK-NEXT: [[END2:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE]], i64 [[N]]
+; CHECK-NEXT: [[END2_INT:%.*]] = ptrtoint ptr [[END2]] to i64
+; CHECK-NEXT: [[OFFSET:%.*]] = sub i64 [[DST_INT]], [[END2_INT]]
+; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[OFFSET]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[SRC]], [[END]]
+; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP_PREHEADER:.*]], [[EXIT:label %.*]]
+; CHECK: [[LOOP_PREHEADER]]:
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], [[END_INT]]
+; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[DST_INT]]
+; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 4
+; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]
+; CHECK: [[VECTOR_MEMCHECK]]:
+; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[N]], [[DST_PTR1]]
+; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP2]], [[DST_INT]]
+; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP3]], 4
+; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]
+;
+entry:
+ %end.int = ptrtoint ptr %end to i64
+ %ext = getelementptr inbounds nuw i8, ptr %end, i64 %n
+ %ext.int = ptrtoint ptr %ext to i64
+ br i1 %cond, label %if.then, label %loop.ph
+
+if.then:
+ br label %loop.ph
+
+loop.ph:
+ %dst.int = phi i64 [ %ext.int, %if.then ], [ %end.int, %entry ]
+ %dst.ptr = phi ptr [ %ext, %if.then ], [ %end, %entry ]
+ %end2 = getelementptr inbounds nuw i8, ptr %base, i64 %n
+ %end2.int = ptrtoint ptr %end2 to i64
+ %offset = sub i64 %dst.int, %end2.int
+ %src = getelementptr inbounds i8, ptr %base, i64 %offset
+ %cmp = icmp ult ptr %src, %end
+ br i1 %cmp, label %loop, label %exit
+
+loop:
+ %iv.src = phi ptr [ %src, %loop.ph ], [ %next.src, %loop ]
+ %iv.dst = phi ptr [ %dst.ptr, %loop.ph ], [ %next.dst, %loop ]
+ %val = load i8, ptr %iv.src, align 1
+ store i8 %val, ptr %iv.dst, align 1
+ %next.src = getelementptr inbounds nuw i8, ptr %iv.src, i64 1
+ %next.dst = getelementptr inbounds nuw i8, ptr %iv.dst, i64 1
+ %done = icmp eq ptr %next.src, %end
+ br i1 %done, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+!0 = distinct !{!0, !1}
+!1 = !{!"llvm.loop.mustprogress"}
>From 7520f35beffba6b6cb35bab10fb1f207c7de2176 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Wed, 18 Mar 2026 12:12:17 +0100
Subject: [PATCH 23/33] [NFC][AArch64] add tests for `is_fpclass` (#187231)
Preparation for https://github.com/llvm/llvm-project/pull/169402
---
llvm/test/CodeGen/AArch64/is_fpclass.ll | 894 ++++++++++++++++++++++++
1 file changed, 894 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/is_fpclass.ll
diff --git a/llvm/test/CodeGen/AArch64/is_fpclass.ll b/llvm/test/CodeGen/AArch64/is_fpclass.ll
new file mode 100644
index 0000000000000..0680c8a1e8fb4
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/is_fpclass.ll
@@ -0,0 +1,894 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64 -global-isel=0 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; RUN: llc -mtriple=armv6m-none-eabi -global-isel=0 < %s | FileCheck %s --check-prefixes=CHECK-SOFTFLOAT
+
+define i1 @isfinite_h(half %x) {
+; CHECK-LABEL: isfinite_h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #31744 // =0x7c00
+; CHECK-NEXT: and w9, w9, #0x7fff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, lt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_h:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ldr r1, .LCPI0_0
+; CHECK-SOFTFLOAT-NEXT: ands r1, r0
+; CHECK-SOFTFLOAT-NEXT: movs r0, #31
+; CHECK-SOFTFLOAT-NEXT: lsls r0, r0, #10
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r0
+; CHECK-SOFTFLOAT-NEXT: blt .LBB0_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .LBB0_2:
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI0_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f16(half %x, i32 504) ; 0x1f8 = "finite"
+ ret i1 %0
+}
+
+define i1 @not_isfinite_h(half %x) {
+; CHECK-LABEL: not_isfinite_h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #31743 // =0x7bff
+; CHECK-NEXT: and w9, w9, #0x7fff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_h:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ldr r1, .LCPI1_0
+; CHECK-SOFTFLOAT-NEXT: ands r1, r0
+; CHECK-SOFTFLOAT-NEXT: ldr r0, .LCPI1_1
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r0
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB1_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .LBB1_2:
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI1_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+; CHECK-SOFTFLOAT-NEXT: .LCPI1_1:
+; CHECK-SOFTFLOAT-NEXT: .long 31743 @ 0x7bff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f16(half %x, i32 519) ; ~0x1f8 = "~finite"
+ ret i1 %0
+}
+
+define i1 @isfinite_f(float %x) {
+; CHECK-LABEL: isfinite_f:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #2139095040 // =0x7f800000
+; CHECK-NEXT: and w9, w9, #0x7fffffff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, lt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_f:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r0
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: movs r2, #255
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r2, #23
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: blt .LBB2_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB2_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504) ; 0x1f8 = "finite"
+ ret i1 %0
+}
+
+define i1 @not_isfinite_f(float %x) {
+; CHECK-LABEL: not_isfinite_f:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #2139095039 // =0x7f7fffff
+; CHECK-NEXT: and w9, w9, #0x7fffffff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_f:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r0
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: ldr r2, .LCPI3_0
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB3_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB3_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI3_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2139095039 @ 0x7f7fffff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 519) ; ~0x1f8 = "~finite"
+ ret i1 %0
+}
+
+
+define i1 @isfinite_f_strictfp(float %x) strictfp {
+; CHECK-LABEL: isfinite_f_strictfp:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #2139095040 // =0x7f800000
+; CHECK-NEXT: and w9, w9, #0x7fffffff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, lt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_f_strictfp:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r0
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: movs r2, #255
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r2, #23
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: blt .LBB4_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB4_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504) strictfp ; 0x1f8 = "finite"
+ ret i1 %0
+}
+
+define i1 @not_isfinite_f_strictfp(float %x) strictfp {
+; CHECK-LABEL: not_isfinite_f_strictfp:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #2139095039 // =0x7f7fffff
+; CHECK-NEXT: and w9, w9, #0x7fffffff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_f_strictfp:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r0
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: ldr r2, .LCPI5_0
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB5_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB5_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI5_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2139095039 @ 0x7f7fffff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 519) strictfp ; ~0x1f8 = ~"finite"
+ ret i1 %0
+}
+
+
+define i1 @isfinite_d(double %x) {
+; CHECK-LABEL: isfinite_d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
+; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-NEXT: cmp x9, x8
+; CHECK-NEXT: cset w0, lt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_d:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: ldr r2, .LCPI6_0
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: blt .LBB6_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB6_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI6_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2146435072 @ 0x7ff00000
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 504) ; 0x1f8 = "finite"
+ ret i1 %0
+}
+
+define i1 @not_isfinite_d(double %x) {
+; CHECK-LABEL: not_isfinite_d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: mov x8, #9218868437227405311 // =0x7fefffffffffffff
+; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-NEXT: cmp x9, x8
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_d:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: ldr r2, .LCPI7_0
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB7_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB7_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI7_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2146435071 @ 0x7fefffff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 519) ; ~0x1f8 = "~finite"
+ ret i1 %0
+}
+
+define i1 @isfinite_d_strictfp(double %x) {
+; CHECK-LABEL: isfinite_d_strictfp:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
+; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-NEXT: cmp x9, x8
+; CHECK-NEXT: cset w0, lt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_d_strictfp:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: ldr r2, .LCPI8_0
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: blt .LBB8_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB8_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI8_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2146435072 @ 0x7ff00000
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 504) strictfp ; 0x1f8 = "finite"
+ ret i1 %0
+}
+
+define i1 @not_isfinite_d_strictfp(double %x) {
+; CHECK-LABEL: not_isfinite_d_strictfp:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov x9, d0
+; CHECK-NEXT: mov x8, #9218868437227405311 // =0x7fefffffffffffff
+; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-NEXT: cmp x9, x8
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_d_strictfp:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r2, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r1, r2
+; CHECK-SOFTFLOAT-NEXT: ldr r2, .LCPI9_0
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r2
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB9_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB9_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI9_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2146435071 @ 0x7fefffff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 519) strictfp ; ~0x1f8 = "~finite"
+ ret i1 %0
+}
+
+define i1 @isfinite_bf16(bfloat %x) {
+; CHECK-LABEL: isfinite_bf16:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #32640 // =0x7f80
+; CHECK-NEXT: and w9, w9, #0x7fff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, lt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_bf16:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ldr r1, .LCPI10_0
+; CHECK-SOFTFLOAT-NEXT: ands r1, r0
+; CHECK-SOFTFLOAT-NEXT: movs r0, #255
+; CHECK-SOFTFLOAT-NEXT: lsls r0, r0, #7
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r0
+; CHECK-SOFTFLOAT-NEXT: blt .LBB10_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .LBB10_2:
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI10_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.bf16(bfloat %x, i32 504) ; 0x1f8 = "finite"
+ ret i1 %0
+}
+
+define i1 @not_isfinite_bf16(bfloat %x) {
+; CHECK-LABEL: not_isfinite_bf16:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0
+; CHECK-NEXT: fmov w9, s0
+; CHECK-NEXT: mov w8, #32639 // =0x7f7f
+; CHECK-NEXT: and w9, w9, #0x7fff
+; CHECK-NEXT: cmp w9, w8
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_bf16:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ldr r1, .LCPI11_0
+; CHECK-SOFTFLOAT-NEXT: ands r1, r0
+; CHECK-SOFTFLOAT-NEXT: ldr r0, .LCPI11_1
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r0
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB11_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .LBB11_2:
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI11_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+; CHECK-SOFTFLOAT-NEXT: .LCPI11_1:
+; CHECK-SOFTFLOAT-NEXT: .long 32639 @ 0x7f7f
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.bf16(bfloat %x, i32 519) ; ~0x1f8 = "~finite"
+ ret i1 %0
+}
+
+define i1 @isfinite_f128(fp128 %x) {
+; CHECK-LABEL: isfinite_f128:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: str q0, [sp, #-16]!
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: ldr x9, [sp, #8]
+; CHECK-NEXT: mov x8, #9223090561878065152 // =0x7fff000000000000
+; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-NEXT: cmp x9, x8
+; CHECK-NEXT: cset w0, lt
+; CHECK-NEXT: add sp, sp, #16
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_f128:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r1, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r3, r1
+; CHECK-SOFTFLOAT-NEXT: ldr r1, .LCPI12_0
+; CHECK-SOFTFLOAT-NEXT: cmp r3, r1
+; CHECK-SOFTFLOAT-NEXT: blt .LBB12_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB12_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI12_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2147418112 @ 0x7fff0000
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f128(fp128 %x, i32 504) ; 0x1f8 = "finite"
+ ret i1 %0
+}
+
+define i1 @not_isfinite_f128(fp128 %x) {
+; CHECK-LABEL: not_isfinite_f128:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: str q0, [sp, #-16]!
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: ldr x9, [sp, #8]
+; CHECK-NEXT: mov x8, #9223090561878065151 // =0x7ffeffffffffffff
+; CHECK-NEXT: and x9, x9, #0x7fffffffffffffff
+; CHECK-NEXT: cmp x9, x8
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: add sp, sp, #16
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_f128:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #1
+; CHECK-SOFTFLOAT-NEXT: lsls r1, r0, #31
+; CHECK-SOFTFLOAT-NEXT: bics r3, r1
+; CHECK-SOFTFLOAT-NEXT: ldr r1, .LCPI13_0
+; CHECK-SOFTFLOAT-NEXT: cmp r3, r1
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB13_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: movs r0, #0
+; CHECK-SOFTFLOAT-NEXT: .LBB13_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: bx lr
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3:
+; CHECK-SOFTFLOAT-NEXT: .LCPI13_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2147418111 @ 0x7ffeffff
+entry:
+ %0 = tail call i1 @llvm.is.fpclass.f128(fp128 %x, i32 519) ; ~0x1f8 = "~finite"
+ ret i1 %0
+}
+
+define <4 x i1> @isfinite_v4h(<4 x half> %x) {
+; CHECK-LABEL: isfinite_v4h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: movi v1.4h, #124, lsl #8
+; CHECK-NEXT: bic v0.4h, #128, lsl #8
+; CHECK-NEXT: cmgt v0.4h, v1.4h, v0.4h
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_v4h:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: ldr r5, .LCPI14_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r5
+; CHECK-SOFTFLOAT-NEXT: movs r4, #31
+; CHECK-SOFTFLOAT-NEXT: lsls r7, r4, #10
+; CHECK-SOFTFLOAT-NEXT: movs r4, #1
+; CHECK-SOFTFLOAT-NEXT: movs r6, #0
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r7
+; CHECK-SOFTFLOAT-NEXT: mov r0, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB14_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB14_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r1, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r7
+; CHECK-SOFTFLOAT-NEXT: mov r1, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB14_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB14_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r2, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r2, r7
+; CHECK-SOFTFLOAT-NEXT: mov r2, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB14_6
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r2, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB14_6: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r3, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r3, r7
+; CHECK-SOFTFLOAT-NEXT: blt .LBB14_8
+; CHECK-SOFTFLOAT-NEXT: @ %bb.7: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r4, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB14_8: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r3, r4
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.9:
+; CHECK-SOFTFLOAT-NEXT: .LCPI14_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+entry:
+ %0 = tail call <4 x i1> @llvm.is.fpclass.v4f16(<4 x half> %x, i32 504) ; 0x1f8 = "finite"
+ ret <4 x i1> %0
+}
+
+define <4 x i1> @not_isfinite_v4h(<4 x half> %x) {
+; CHECK-LABEL: not_isfinite_v4h:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: movi v1.4h, #124, lsl #8
+; CHECK-NEXT: bic v0.4h, #128, lsl #8
+; CHECK-NEXT: cmge v0.4h, v0.4h, v1.4h
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_v4h:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: mov r4, r3
+; CHECK-SOFTFLOAT-NEXT: ldr r6, .LCPI15_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r6
+; CHECK-SOFTFLOAT-NEXT: movs r3, #1
+; CHECK-SOFTFLOAT-NEXT: movs r5, #0
+; CHECK-SOFTFLOAT-NEXT: ldr r7, .LCPI15_1
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r7
+; CHECK-SOFTFLOAT-NEXT: mov r0, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB15_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB15_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r1, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r7
+; CHECK-SOFTFLOAT-NEXT: mov r1, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB15_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB15_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r2, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r2, r7
+; CHECK-SOFTFLOAT-NEXT: mov r2, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB15_6
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r2, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB15_6: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r4, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r4, r7
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB15_8
+; CHECK-SOFTFLOAT-NEXT: @ %bb.7: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r3, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB15_8: @ %entry
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.9:
+; CHECK-SOFTFLOAT-NEXT: .LCPI15_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+; CHECK-SOFTFLOAT-NEXT: .LCPI15_1:
+; CHECK-SOFTFLOAT-NEXT: .long 31743 @ 0x7bff
+entry:
+ %0 = tail call <4 x i1> @llvm.is.fpclass.v4f16(<4 x half> %x, i32 519) ; ~0x1f8 = "~finite"
+ ret <4 x i1> %0
+}
+
+define <4 x i1> @isfinite_v4f(<4 x float> %x) {
+; CHECK-LABEL: isfinite_v4f:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mvni v1.4s, #127, msl #16
+; CHECK-NEXT: fabs v0.4s, v0.4s
+; CHECK-NEXT: fneg v1.4s, v1.4s
+; CHECK-NEXT: fcmgt v2.4s, v0.4s, v1.4s
+; CHECK-NEXT: fcmgt v0.4s, v1.4s, v0.4s
+; CHECK-NEXT: orr v0.16b, v0.16b, v2.16b
+; CHECK-NEXT: xtn v0.4h, v0.4s
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_v4f:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: ldr r5, .LCPI16_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r5
+; CHECK-SOFTFLOAT-NEXT: movs r4, #255
+; CHECK-SOFTFLOAT-NEXT: lsls r7, r4, #23
+; CHECK-SOFTFLOAT-NEXT: movs r4, #1
+; CHECK-SOFTFLOAT-NEXT: movs r6, #0
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r7
+; CHECK-SOFTFLOAT-NEXT: mov r0, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB16_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB16_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r1, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r7
+; CHECK-SOFTFLOAT-NEXT: mov r1, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB16_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB16_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r2, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r2, r7
+; CHECK-SOFTFLOAT-NEXT: mov r2, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB16_6
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r2, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB16_6: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r3, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r3, r7
+; CHECK-SOFTFLOAT-NEXT: blt .LBB16_8
+; CHECK-SOFTFLOAT-NEXT: @ %bb.7: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r4, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB16_8: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r3, r4
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.9:
+; CHECK-SOFTFLOAT-NEXT: .LCPI16_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2147483647 @ 0x7fffffff
+entry:
+ %0 = tail call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %x, i32 504) ; 0x1f8 = "finite"
+ ret <4 x i1> %0
+}
+
+define <4 x i1> @not_isfinite_v4f(<4 x float> %x) {
+; CHECK-LABEL: not_isfinite_v4f:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mvni v1.4s, #127, msl #16
+; CHECK-NEXT: bic v0.4s, #128, lsl #24
+; CHECK-NEXT: fneg v1.4s, v1.4s
+; CHECK-NEXT: cmge v0.4s, v0.4s, v1.4s
+; CHECK-NEXT: xtn v0.4h, v0.4s
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_v4f:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: mov r4, r3
+; CHECK-SOFTFLOAT-NEXT: ldr r6, .LCPI17_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r6
+; CHECK-SOFTFLOAT-NEXT: movs r3, #1
+; CHECK-SOFTFLOAT-NEXT: movs r5, #0
+; CHECK-SOFTFLOAT-NEXT: ldr r7, .LCPI17_1
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r7
+; CHECK-SOFTFLOAT-NEXT: mov r0, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB17_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB17_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r1, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r7
+; CHECK-SOFTFLOAT-NEXT: mov r1, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB17_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB17_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r2, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r2, r7
+; CHECK-SOFTFLOAT-NEXT: mov r2, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB17_6
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r2, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB17_6: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r4, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r4, r7
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB17_8
+; CHECK-SOFTFLOAT-NEXT: @ %bb.7: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r3, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB17_8: @ %entry
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.9:
+; CHECK-SOFTFLOAT-NEXT: .LCPI17_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2147483647 @ 0x7fffffff
+; CHECK-SOFTFLOAT-NEXT: .LCPI17_1:
+; CHECK-SOFTFLOAT-NEXT: .long 2139095039 @ 0x7f7fffff
+entry:
+ %0 = tail call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %x, i32 519) ; ~0x1f8 = "~finite"
+ ret <4 x i1> %0
+}
+
+define <2 x i1> @isfinite_v2d(<2 x double> %x) {
+; CHECK-LABEL: isfinite_v2d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
+; CHECK-NEXT: fabs v0.2d, v0.2d
+; CHECK-NEXT: dup v1.2d, x8
+; CHECK-NEXT: fcmgt v2.2d, v0.2d, v1.2d
+; CHECK-NEXT: fcmgt v0.2d, v1.2d, v0.2d
+; CHECK-NEXT: orr v0.16b, v0.16b, v2.16b
+; CHECK-NEXT: xtn v0.2s, v0.2d
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_v2d:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: mov r0, r1
+; CHECK-SOFTFLOAT-NEXT: ldr r4, .LCPI18_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r4
+; CHECK-SOFTFLOAT-NEXT: movs r1, #1
+; CHECK-SOFTFLOAT-NEXT: movs r2, #0
+; CHECK-SOFTFLOAT-NEXT: ldr r5, .LCPI18_1
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r5
+; CHECK-SOFTFLOAT-NEXT: mov r0, r1
+; CHECK-SOFTFLOAT-NEXT: blt .LBB18_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r2
+; CHECK-SOFTFLOAT-NEXT: .LBB18_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r3, r4
+; CHECK-SOFTFLOAT-NEXT: cmp r3, r5
+; CHECK-SOFTFLOAT-NEXT: blt .LBB18_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r2
+; CHECK-SOFTFLOAT-NEXT: .LBB18_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5:
+; CHECK-SOFTFLOAT-NEXT: .LCPI18_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2147483647 @ 0x7fffffff
+; CHECK-SOFTFLOAT-NEXT: .LCPI18_1:
+; CHECK-SOFTFLOAT-NEXT: .long 2146435072 @ 0x7ff00000
+entry:
+ %0 = tail call <2 x i1> @llvm.is.fpclass.v2f64(<2 x double> %x, i32 504) ; 0x1f8 = "finite"
+ ret <2 x i1> %0
+}
+
+define <2 x i1> @not_isfinite_v2d(<2 x double> %x) {
+; CHECK-LABEL: not_isfinite_v2d:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: movi v1.2d, #0xffffffffffffffff
+; CHECK-NEXT: mov x8, #9218868437227405312 // =0x7ff0000000000000
+; CHECK-NEXT: fneg v1.2d, v1.2d
+; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: dup v1.2d, x8
+; CHECK-NEXT: cmge v0.2d, v0.2d, v1.2d
+; CHECK-NEXT: xtn v0.2s, v0.2d
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_v2d:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: mov r0, r1
+; CHECK-SOFTFLOAT-NEXT: ldr r4, .LCPI19_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r4
+; CHECK-SOFTFLOAT-NEXT: movs r1, #1
+; CHECK-SOFTFLOAT-NEXT: movs r2, #0
+; CHECK-SOFTFLOAT-NEXT: ldr r5, .LCPI19_1
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r5
+; CHECK-SOFTFLOAT-NEXT: mov r0, r1
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB19_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r2
+; CHECK-SOFTFLOAT-NEXT: .LBB19_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r3, r4
+; CHECK-SOFTFLOAT-NEXT: cmp r3, r5
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB19_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r2
+; CHECK-SOFTFLOAT-NEXT: .LBB19_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5:
+; CHECK-SOFTFLOAT-NEXT: .LCPI19_0:
+; CHECK-SOFTFLOAT-NEXT: .long 2147483647 @ 0x7fffffff
+; CHECK-SOFTFLOAT-NEXT: .LCPI19_1:
+; CHECK-SOFTFLOAT-NEXT: .long 2146435071 @ 0x7fefffff
+entry:
+ %0 = tail call <2 x i1> @llvm.is.fpclass.v2f64(<2 x double> %x, i32 519) ; ~0x1f8 = "~finite"
+ ret <2 x i1> %0
+}
+
+define <4 x i1> @isfinite_v4bf16(<4 x bfloat> %x) {
+; CHECK-LABEL: isfinite_v4bf16:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov w8, #32640 // =0x7f80
+; CHECK-NEXT: bic v0.4h, #128, lsl #8
+; CHECK-NEXT: dup v1.4h, w8
+; CHECK-NEXT: cmgt v0.4h, v1.4h, v0.4h
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: isfinite_v4bf16:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: ldr r5, .LCPI20_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r5
+; CHECK-SOFTFLOAT-NEXT: movs r4, #255
+; CHECK-SOFTFLOAT-NEXT: lsls r7, r4, #7
+; CHECK-SOFTFLOAT-NEXT: movs r4, #1
+; CHECK-SOFTFLOAT-NEXT: movs r6, #0
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r7
+; CHECK-SOFTFLOAT-NEXT: mov r0, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB20_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB20_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r1, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r7
+; CHECK-SOFTFLOAT-NEXT: mov r1, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB20_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB20_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r2, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r2, r7
+; CHECK-SOFTFLOAT-NEXT: mov r2, r4
+; CHECK-SOFTFLOAT-NEXT: blt .LBB20_6
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r2, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB20_6: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r3, r5
+; CHECK-SOFTFLOAT-NEXT: cmp r3, r7
+; CHECK-SOFTFLOAT-NEXT: blt .LBB20_8
+; CHECK-SOFTFLOAT-NEXT: @ %bb.7: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r4, r6
+; CHECK-SOFTFLOAT-NEXT: .LBB20_8: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r3, r4
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.9:
+; CHECK-SOFTFLOAT-NEXT: .LCPI20_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+entry:
+ %0 = tail call <4 x i1> @llvm.is.fpclass.v4bf16(<4 x bfloat> %x, i32 504) ; 0x1f8 = "finite"
+ ret <4 x i1> %0
+}
+
+define <4 x i1> @not_isfinite_v4bf16(<4 x bfloat> %x) {
+; CHECK-LABEL: not_isfinite_v4bf16:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov w8, #32640 // =0x7f80
+; CHECK-NEXT: bic v0.4h, #128, lsl #8
+; CHECK-NEXT: dup v1.4h, w8
+; CHECK-NEXT: cmge v0.4h, v0.4h, v1.4h
+; CHECK-NEXT: ret
+;
+; CHECK-SOFTFLOAT-LABEL: not_isfinite_v4bf16:
+; CHECK-SOFTFLOAT: @ %bb.0: @ %entry
+; CHECK-SOFTFLOAT-NEXT: .save {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-SOFTFLOAT-NEXT: mov r4, r3
+; CHECK-SOFTFLOAT-NEXT: ldr r6, .LCPI21_0
+; CHECK-SOFTFLOAT-NEXT: ands r0, r6
+; CHECK-SOFTFLOAT-NEXT: movs r3, #1
+; CHECK-SOFTFLOAT-NEXT: movs r5, #0
+; CHECK-SOFTFLOAT-NEXT: ldr r7, .LCPI21_1
+; CHECK-SOFTFLOAT-NEXT: cmp r0, r7
+; CHECK-SOFTFLOAT-NEXT: mov r0, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB21_2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.1: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r0, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB21_2: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r1, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r1, r7
+; CHECK-SOFTFLOAT-NEXT: mov r1, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB21_4
+; CHECK-SOFTFLOAT-NEXT: @ %bb.3: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r1, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB21_4: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r2, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r2, r7
+; CHECK-SOFTFLOAT-NEXT: mov r2, r3
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB21_6
+; CHECK-SOFTFLOAT-NEXT: @ %bb.5: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r2, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB21_6: @ %entry
+; CHECK-SOFTFLOAT-NEXT: ands r4, r6
+; CHECK-SOFTFLOAT-NEXT: cmp r4, r7
+; CHECK-SOFTFLOAT-NEXT: bgt .LBB21_8
+; CHECK-SOFTFLOAT-NEXT: @ %bb.7: @ %entry
+; CHECK-SOFTFLOAT-NEXT: mov r3, r5
+; CHECK-SOFTFLOAT-NEXT: .LBB21_8: @ %entry
+; CHECK-SOFTFLOAT-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-SOFTFLOAT-NEXT: .p2align 2
+; CHECK-SOFTFLOAT-NEXT: @ %bb.9:
+; CHECK-SOFTFLOAT-NEXT: .LCPI21_0:
+; CHECK-SOFTFLOAT-NEXT: .long 32767 @ 0x7fff
+; CHECK-SOFTFLOAT-NEXT: .LCPI21_1:
+; CHECK-SOFTFLOAT-NEXT: .long 32639 @ 0x7f7f
+entry:
+ %0 = tail call <4 x i1> @llvm.is.fpclass.v4bf16(<4 x bfloat> %x, i32 519) ; ~0x1f8 = "~finite"
+ ret <4 x i1> %0
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-GI: {{.*}}
+; CHECK-SD: {{.*}}
>From a060150291105677db5a1967430826947073ffd5 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Wed, 18 Mar 2026 22:17:04 +1100
Subject: [PATCH 24/33] [orc-rt] Move CallViaSession into Session, add
comments. (#187238)
Makes CallViaSession an inner class on Session, and adds comments and a
convenience method for creating instances.
---
orc-rt/include/orc-rt/Session.h | 43 +++++++++++++++++++++-----------
orc-rt/unittests/SessionTest.cpp | 6 ++---
2 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/orc-rt/include/orc-rt/Session.h b/orc-rt/include/orc-rt/Session.h
index 9d64afaee8f25..287ff7ea0777d 100644
--- a/orc-rt/include/orc-rt/Session.h
+++ b/orc-rt/include/orc-rt/Session.h
@@ -171,6 +171,11 @@ class Session {
/// Disconnect the ControllerAccess object.
void detach();
+ /// Call a tagged handler in the Controller.
+ ///
+ /// This method can be called directly, but is expected to be more commonly
+ /// called by the WrapperFunction::call method using a CallViaSession object
+ /// (see below).
void callController(OnCallHandlerCompleteFn OnComplete, HandlerTag T,
WrapperFunctionBuffer ArgBytes) {
if (auto TmpCA = CA)
@@ -180,6 +185,30 @@ class Session {
"no controller attached"));
}
+ /// Provides an async method interface to call, via the given Session, the
+ /// controller handler with the given tag.
+ ///
+ /// Useable as a Caller implementation with WrapperFunction::call.
+ class CallViaSession {
+ public:
+ CallViaSession(Session &S, HandlerTag T) : S(S), T(T) {}
+
+ void operator()(OnCallHandlerCompleteFn &&HandleResult,
+ WrapperFunctionBuffer ArgBytes) {
+ S.callController(std::move(HandleResult), T, std::move(ArgBytes));
+ }
+
+ private:
+ Session &S;
+ HandlerTag T;
+ };
+
+ /// Get a WrapperFunction::call-compatible Caller that will call through to
+ /// the handler with the given tag.
+ CallViaSession callViaSession(HandlerTag T) noexcept {
+ return CallViaSession(*this, T);
+ }
+
private:
struct ShutdownInfo {
bool Complete = false;
@@ -215,20 +244,6 @@ class Session {
std::unique_ptr<ShutdownInfo> SI;
};
-class CallViaSession {
-public:
- CallViaSession(Session &S, Session::HandlerTag T) : S(S), T(T) {}
-
- void operator()(Session::OnCallHandlerCompleteFn &&HandleResult,
- WrapperFunctionBuffer ArgBytes) {
- S.callController(std::move(HandleResult), T, std::move(ArgBytes));
- }
-
-private:
- Session &S;
- Session::HandlerTag T;
-};
-
} // namespace orc_rt
#endif // ORC_RT_SESSION_H
diff --git a/orc-rt/unittests/SessionTest.cpp b/orc-rt/unittests/SessionTest.cpp
index f131ccb61c2a2..fd873c5e81469 100644
--- a/orc-rt/unittests/SessionTest.cpp
+++ b/orc-rt/unittests/SessionTest.cpp
@@ -420,7 +420,7 @@ TEST(ControllerAccessTest, ValidCallToController) {
int32_t Result = 0;
SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(
- CallViaSession(S, reinterpret_cast<Session::HandlerTag>(add_sps_wrapper)),
+ S.callViaSession(reinterpret_cast<Session::HandlerTag>(add_sps_wrapper)),
[&](Expected<int32_t> R) { Result = cantFail(std::move(R)); }, 41, 1);
EnqueueingDispatcher::runTasksFromFront(Tasks);
@@ -438,7 +438,7 @@ TEST(ControllerAccessTest, CallToControllerBeforeAttach) {
Error Err = Error::success();
SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(
- CallViaSession(S, reinterpret_cast<Session::HandlerTag>(add_sps_wrapper)),
+ S.callViaSession(reinterpret_cast<Session::HandlerTag>(add_sps_wrapper)),
[&](Expected<int32_t> R) {
ErrorAsOutParameter _(Err);
Err = R.takeError();
@@ -462,7 +462,7 @@ TEST(ControllerAccessTest, CallToControllerAfterDetach) {
Error Err = Error::success();
SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(
- CallViaSession(S, reinterpret_cast<Session::HandlerTag>(add_sps_wrapper)),
+ S.callViaSession(reinterpret_cast<Session::HandlerTag>(add_sps_wrapper)),
[&](Expected<int32_t> R) {
ErrorAsOutParameter _(Err);
Err = R.takeError();
>From 2322e04d9f63ea6166b11c5eaf94f0db5a91cec1 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 18 Mar 2026 12:20:32 +0100
Subject: [PATCH 25/33] [CycleInfo] Use block numbers for dfs numbering (NFC)
(#187062)
Store the DFSInfo into a vector indexed by block number instead of a map
using the block pointer.
This is a small compile-time improvement for CycleInfo construction.
---
llvm/include/llvm/ADT/GenericCycleImpl.h | 41 ++++++++++++++++--------
1 file changed, 28 insertions(+), 13 deletions(-)
diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index 00f85ca819f3f..045e3167b9dd3 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -227,6 +227,7 @@ void GenericCycle<ContextT>::verifyCycleNest() const {
/// \brief Helper class for computing cycle information.
template <typename ContextT> class GenericCycleInfoCompute {
using BlockT = typename ContextT::BlockT;
+ using FunctionT = typename ContextT::FunctionT;
using CycleInfoT = GenericCycleInfo<ContextT>;
using CycleT = typename CycleInfoT::CycleT;
@@ -248,21 +249,32 @@ template <typename ContextT> class GenericCycleInfoCompute {
}
};
- DenseMap<BlockT *, DFSInfo> BlockDFSInfo;
+ // Indexed by block number.
+ SmallVector<DFSInfo, 8> BlockDFSInfo;
SmallVector<BlockT *, 8> BlockPreorder;
GenericCycleInfoCompute(const GenericCycleInfoCompute &) = delete;
GenericCycleInfoCompute &operator=(const GenericCycleInfoCompute &) = delete;
+ DFSInfo getDFSInfo(BlockT *B) const {
+ unsigned Number = GraphTraits<BlockT *>::getNumber(B);
+ return BlockDFSInfo[Number];
+ }
+
+ DFSInfo &getOrInsertDFSInfo(BlockT *B) {
+ unsigned Number = GraphTraits<BlockT *>::getNumber(B);
+ return BlockDFSInfo[Number];
+ }
+
public:
GenericCycleInfoCompute(CycleInfoT &Info) : Info(Info) {}
- void run(BlockT *EntryBlock);
+ void run(FunctionT *F);
static void updateDepth(CycleT *SubTree);
private:
- void dfs(BlockT *EntryBlock);
+ void dfs(FunctionT *F, BlockT *EntryBlock);
};
template <typename ContextT>
@@ -329,18 +341,19 @@ void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
/// \brief Main function of the cycle info computations.
template <typename ContextT>
-void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
+void GenericCycleInfoCompute<ContextT>::run(FunctionT *F) {
+ BlockT *EntryBlock = GraphTraits<FunctionT *>::getEntryNode(F);
LLVM_DEBUG(errs() << "Entry block: " << Info.Context.print(EntryBlock)
<< "\n");
- dfs(EntryBlock);
+ dfs(F, EntryBlock);
SmallVector<BlockT *, 8> Worklist;
for (BlockT *HeaderCandidate : llvm::reverse(BlockPreorder)) {
- const DFSInfo CandidateInfo = BlockDFSInfo.lookup(HeaderCandidate);
+ const DFSInfo CandidateInfo = getDFSInfo(HeaderCandidate);
for (BlockT *Pred : predecessors(HeaderCandidate)) {
- const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
+ const DFSInfo PredDFSInfo = getDFSInfo(Pred);
// This automatically ignores unreachable predecessors since they have
// zeros in their DFSInfo.
if (CandidateInfo.isAncestorOf(PredDFSInfo))
@@ -366,7 +379,7 @@ void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
bool IsEntry = false;
for (BlockT *Pred : predecessors(Block)) {
- const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
+ const DFSInfo PredDFSInfo = getDFSInfo(Pred);
if (CandidateInfo.isAncestorOf(PredDFSInfo)) {
Worklist.push_back(Pred);
} else if (!PredDFSInfo) {
@@ -444,18 +457,20 @@ void GenericCycleInfoCompute<ContextT>::updateDepth(CycleT *SubTree) {
///
/// Fills BlockDFSInfo with start/end counters and BlockPreorder.
template <typename ContextT>
-void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
+void GenericCycleInfoCompute<ContextT>::dfs(FunctionT *F, BlockT *EntryBlock) {
SmallVector<unsigned, 8> DFSTreeStack;
SmallVector<BlockT *, 8> TraverseStack;
unsigned Counter = 0;
TraverseStack.emplace_back(EntryBlock);
+ BlockDFSInfo.resize(GraphTraits<FunctionT *>::getMaxNumber(F));
do {
BlockT *Block = TraverseStack.back();
LLVM_DEBUG(errs() << "DFS visiting block: " << Info.Context.print(Block)
<< "\n");
- if (BlockDFSInfo.try_emplace(Block, Counter + 1).second) {
- ++Counter;
+ DFSInfo &Info = getOrInsertDFSInfo(Block);
+ if (Info.Start == 0) {
+ Info.Start = ++Counter;
// We're visiting the block for the first time. Open its DFSInfo, add
// successors to the traversal stack, and remember the traversal stack
@@ -473,7 +488,7 @@ void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
assert(!DFSTreeStack.empty());
if (DFSTreeStack.back() == TraverseStack.size()) {
LLVM_DEBUG(errs() << " ended at " << Counter << "\n");
- BlockDFSInfo.find(Block)->second.End = Counter;
+ Info.End = Counter;
DFSTreeStack.pop_back();
} else {
LLVM_DEBUG(errs() << " already done\n");
@@ -506,7 +521,7 @@ void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName()
<< "\n");
- Compute.run(&F.front());
+ Compute.run(&F);
}
template <typename ContextT>
>From 87b068193332982b2df72382bf989bdb83395cb5 Mon Sep 17 00:00:00 2001
From: Sander de Smalen <sander.desmalen at arm.com>
Date: Wed, 18 Mar 2026 11:24:04 +0000
Subject: [PATCH 26/33] [AArch64] Use SVE/NEON FMLAL top/bottom instructions
(#186798)
---
.../Target/AArch64/AArch64ISelLowering.cpp | 4 +-
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 7 +++
.../lib/Target/AArch64/AArch64SVEInstrInfo.td | 4 ++
.../AArch64/f16f32dot-fixed-length-fdot.ll | 57 +++++++++++++++----
llvm/test/CodeGen/AArch64/sve2p1-fdot.ll | 25 ++------
.../AArch64/sve2p1-fixed-length-fdot.ll | 42 ++++++--------
6 files changed, 82 insertions(+), 57 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 7d23d72cc789f..38db1ac4a2fb9 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1509,7 +1509,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
}
}
- if (Subtarget->hasF16F32DOT()) {
+ if (Subtarget->hasF16F32DOT() || Subtarget->hasFP16FML()) {
setPartialReduceMLAAction(ISD::PARTIAL_REDUCE_FMLA, MVT::v2f32,
MVT::v4f16, Legal);
setPartialReduceMLAAction(ISD::PARTIAL_REDUCE_FMLA, MVT::v4f32,
@@ -2039,7 +2039,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
}
// Handle floating-point partial reduction
- if (Subtarget->hasSVE2p1() || Subtarget->hasSME2()) {
+ if (Subtarget->hasSVE2() || Subtarget->hasSME()) {
setPartialReduceMLAAction(ISD::PARTIAL_REDUCE_FMLA, MVT::nxv4f32,
MVT::nxv8f16, Legal);
// We can use SVE2p1 fdot to emulate the fixed-length variant.
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 208bb5ce6b42b..44968b14b11a9 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1824,6 +1824,13 @@ defm FMLALlane : SIMDThreeSameVectorFMLIndex<0, 0b0000, "fmlal", int_aarch64_ne
defm FMLSLlane : SIMDThreeSameVectorFMLIndex<0, 0b0100, "fmlsl", int_aarch64_neon_fmlsl>;
defm FMLAL2lane : SIMDThreeSameVectorFMLIndex<1, 0b1000, "fmlal2", int_aarch64_neon_fmlal2>;
defm FMLSL2lane : SIMDThreeSameVectorFMLIndex<1, 0b1100, "fmlsl2", int_aarch64_neon_fmlsl2>;
+
+def : Pat<(v2f32 (partial_reduce_fmla v2f32:$acc, v4f16:$LHS, v4f16:$RHS)),
+ (FMLAL2v4f16 (FMLALv4f16 v2f32:$acc, V64:$LHS, V64:$RHS),
+ V64:$LHS, V64:$RHS)>;
+def : Pat<(v4f32 (partial_reduce_fmla v4f32:$acc, v8f16:$LHS, v8f16:$RHS)),
+ (FMLAL2v8f16 (FMLALv8f16 v4f32:$acc, V128:$LHS, V128:$RHS),
+ V128:$LHS, V128:$RHS)>;
}
// Armv8.2-A Crypto extensions
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index fe6b5b3d0e51f..8b440ef5e6239 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -4162,6 +4162,10 @@ let Predicates = [HasSVE2_or_SME] in {
defm BSL2N_ZZZZ : sve2_int_bitwise_ternary_op<0b101, "bsl2n", AArch64bsl2n>;
defm NBSL_ZZZZ : sve2_int_bitwise_ternary_op<0b111, "nbsl", AArch64nbsl>;
+ def : Pat<(nxv4f32 (partial_reduce_fmla nxv4f32:$acc, nxv8f16:$LHS, nxv8f16:$RHS)),
+ (FMLALT_ZZZ_SHH (FMLALB_ZZZ_SHH nxv4f32:$acc, ZPR:$LHS, ZPR:$RHS),
+ ZPR:$LHS, ZPR:$RHS)>;
+
// Pseudos for commutable operations that expand to NBSL or BSL2N. These can
// avoid a COPY if one of the source registers can be clobbered, or otherwise
// use a MOVPRFX.
diff --git a/llvm/test/CodeGen/AArch64/f16f32dot-fixed-length-fdot.ll b/llvm/test/CodeGen/AArch64/f16f32dot-fixed-length-fdot.ll
index 2645cfdfc0c89..5b1fe56244fbe 100644
--- a/llvm/test/CodeGen/AArch64/f16f32dot-fixed-length-fdot.ll
+++ b/llvm/test/CodeGen/AArch64/f16f32dot-fixed-length-fdot.ll
@@ -1,13 +1,34 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -mattr=+f16f32dot < %s | FileCheck %s --check-prefixes=CHECK
+; RUN: llc < %s | FileCheck %s --check-prefixes=CHECK-EXPAND
+; RUN: llc -mattr=+fp16fml < %s | FileCheck %s --check-prefixes=CHECK-FMLAL
+; RUN: llc -mattr=+f16f32dot < %s | FileCheck %s --check-prefixes=CHECK-FDOT
+; RUN: llc -mattr=+f16f32dot,+fp16fml < %s | FileCheck %s --check-prefixes=CHECK-FDOT
target triple = "aarch64-linux-gnu"
define <4 x float> @fixed_fdot_wide(<4 x float> %acc, <8 x half> %a, <8 x half> %b) {
-; CHECK-LABEL: fixed_fdot_wide:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fdot v0.4s, v1.8h, v2.8h
-; CHECK-NEXT: ret
+; CHECK-EXPAND-LABEL: fixed_fdot_wide:
+; CHECK-EXPAND: // %bb.0: // %entry
+; CHECK-EXPAND-NEXT: fcvtl v3.4s, v1.4h
+; CHECK-EXPAND-NEXT: fcvtl v4.4s, v2.4h
+; CHECK-EXPAND-NEXT: fcvtl2 v1.4s, v1.8h
+; CHECK-EXPAND-NEXT: fcvtl2 v2.4s, v2.8h
+; CHECK-EXPAND-NEXT: fmul v3.4s, v3.4s, v4.4s
+; CHECK-EXPAND-NEXT: fmul v1.4s, v1.4s, v2.4s
+; CHECK-EXPAND-NEXT: fadd v0.4s, v0.4s, v3.4s
+; CHECK-EXPAND-NEXT: fadd v0.4s, v0.4s, v1.4s
+; CHECK-EXPAND-NEXT: ret
+;
+; CHECK-FMLAL-LABEL: fixed_fdot_wide:
+; CHECK-FMLAL: // %bb.0: // %entry
+; CHECK-FMLAL-NEXT: fmlal v0.4s, v1.4h, v2.4h
+; CHECK-FMLAL-NEXT: fmlal2 v0.4s, v1.4h, v2.4h
+; CHECK-FMLAL-NEXT: ret
+;
+; CHECK-FDOT-LABEL: fixed_fdot_wide:
+; CHECK-FDOT: // %bb.0: // %entry
+; CHECK-FDOT-NEXT: fdot v0.4s, v1.8h, v2.8h
+; CHECK-FDOT-NEXT: ret
entry:
%a.wide = fpext <8 x half> %a to <8 x float>
%b.wide = fpext <8 x half> %b to <8 x float>
@@ -17,14 +38,30 @@ entry:
}
define <2 x float> @fixed_fdot(<2 x float> %acc, <4 x half> %a, <4 x half> %b) {
-; CHECK-LABEL: fixed_fdot:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fdot v0.2s, v1.4h, v2.4h
-; CHECK-NEXT: ret
+; CHECK-EXPAND-LABEL: fixed_fdot:
+; CHECK-EXPAND: // %bb.0: // %entry
+; CHECK-EXPAND-NEXT: fcvtl v1.4s, v1.4h
+; CHECK-EXPAND-NEXT: fcvtl v2.4s, v2.4h
+; CHECK-EXPAND-NEXT: fmul v1.4s, v1.4s, v2.4s
+; CHECK-EXPAND-NEXT: fadd v0.2s, v0.2s, v1.2s
+; CHECK-EXPAND-NEXT: ext v1.16b, v1.16b, v1.16b, #8
+; CHECK-EXPAND-NEXT: fadd v0.2s, v1.2s, v0.2s
+; CHECK-EXPAND-NEXT: ret
+;
+; CHECK-FMLAL-LABEL: fixed_fdot:
+; CHECK-FMLAL: // %bb.0: // %entry
+; CHECK-FMLAL-NEXT: fmlal v0.2s, v1.2h, v2.2h
+; CHECK-FMLAL-NEXT: fmlal2 v0.2s, v1.2h, v2.2h
+; CHECK-FMLAL-NEXT: ret
+;
+; CHECK-FDOT-LABEL: fixed_fdot:
+; CHECK-FDOT: // %bb.0: // %entry
+; CHECK-FDOT-NEXT: fdot v0.2s, v1.4h, v2.4h
+; CHECK-FDOT-NEXT: ret
entry:
%a.wide = fpext <4 x half> %a to <4 x float>
%b.wide = fpext <4 x half> %b to <4 x float>
%mult = fmul <4 x float> %a.wide, %b.wide
%partial.reduce = call <2 x float> @llvm.vector.partial.reduce.fadd(<2 x float> %acc, <4 x float> %mult)
ret <2 x float> %partial.reduce
-}
\ No newline at end of file
+}
diff --git a/llvm/test/CodeGen/AArch64/sve2p1-fdot.ll b/llvm/test/CodeGen/AArch64/sve2p1-fdot.ll
index 9dbe096ebdb57..d3954dc6bf8d6 100644
--- a/llvm/test/CodeGen/AArch64/sve2p1-fdot.ll
+++ b/llvm/test/CodeGen/AArch64/sve2p1-fdot.ll
@@ -9,19 +9,8 @@ target triple = "aarch64-linux-gnu"
define <vscale x 4 x float> @fdot_wide_nxv4f32(<vscale x 4 x float> %acc, <vscale x 8 x half> %a, <vscale x 8 x half> %b) {
; SVE2-LABEL: fdot_wide_nxv4f32:
; SVE2: // %bb.0: // %entry
-; SVE2-NEXT: uunpklo z3.s, z1.h
-; SVE2-NEXT: uunpklo z4.s, z2.h
-; SVE2-NEXT: ptrue p0.s
-; SVE2-NEXT: uunpkhi z1.s, z1.h
-; SVE2-NEXT: uunpkhi z2.s, z2.h
-; SVE2-NEXT: fcvt z3.s, p0/m, z3.h
-; SVE2-NEXT: fcvt z4.s, p0/m, z4.h
-; SVE2-NEXT: fcvt z1.s, p0/m, z1.h
-; SVE2-NEXT: fcvt z2.s, p0/m, z2.h
-; SVE2-NEXT: fmul z3.s, z3.s, z4.s
-; SVE2-NEXT: fmul z1.s, z1.s, z2.s
-; SVE2-NEXT: fadd z0.s, z0.s, z3.s
-; SVE2-NEXT: fadd z0.s, z0.s, z1.s
+; SVE2-NEXT: fmlalb z0.s, z1.h, z2.h
+; SVE2-NEXT: fmlalt z0.s, z1.h, z2.h
; SVE2-NEXT: ret
;
; SVE2P1-LABEL: fdot_wide_nxv4f32:
@@ -39,13 +28,9 @@ entry:
define <vscale x 4 x float> @fdot_splat_nxv4f32(<vscale x 4 x float> %acc, <vscale x 8 x half> %a) {
; SVE2-LABEL: fdot_splat_nxv4f32:
; SVE2: // %bb.0: // %entry
-; SVE2-NEXT: uunpklo z2.s, z1.h
-; SVE2-NEXT: ptrue p0.s
-; SVE2-NEXT: uunpkhi z1.s, z1.h
-; SVE2-NEXT: fcvt z2.s, p0/m, z2.h
-; SVE2-NEXT: fcvt z1.s, p0/m, z1.h
-; SVE2-NEXT: fadd z0.s, z0.s, z2.s
-; SVE2-NEXT: fadd z0.s, z0.s, z1.s
+; SVE2-NEXT: fmov z2.h, #1.00000000
+; SVE2-NEXT: fmlalb z0.s, z1.h, z2.h
+; SVE2-NEXT: fmlalt z0.s, z1.h, z2.h
; SVE2-NEXT: ret
;
; SVE2P1-LABEL: fdot_splat_nxv4f32:
diff --git a/llvm/test/CodeGen/AArch64/sve2p1-fixed-length-fdot.ll b/llvm/test/CodeGen/AArch64/sve2p1-fixed-length-fdot.ll
index 4463b072f69cf..76b39ba429a0d 100644
--- a/llvm/test/CodeGen/AArch64/sve2p1-fixed-length-fdot.ll
+++ b/llvm/test/CodeGen/AArch64/sve2p1-fixed-length-fdot.ll
@@ -7,17 +7,11 @@ target triple = "aarch64-linux-gnu"
define void @fdot_v4f32(ptr %accptr, ptr %aptr, ptr %bptr) {
; SVE2-LABEL: fdot_v4f32:
; SVE2: // %bb.0: // %entry
-; SVE2-NEXT: ldr q0, [x1]
-; SVE2-NEXT: ldr q1, [x2]
-; SVE2-NEXT: fcvtl v2.4s, v0.4h
-; SVE2-NEXT: fcvtl v3.4s, v1.4h
-; SVE2-NEXT: fcvtl2 v0.4s, v0.8h
-; SVE2-NEXT: fcvtl2 v1.4s, v1.8h
-; SVE2-NEXT: fmul v2.4s, v2.4s, v3.4s
-; SVE2-NEXT: ldr q3, [x0]
-; SVE2-NEXT: fmul v0.4s, v0.4s, v1.4s
-; SVE2-NEXT: fadd v1.4s, v3.4s, v2.4s
-; SVE2-NEXT: fadd v0.4s, v1.4s, v0.4s
+; SVE2-NEXT: ldr q0, [x0]
+; SVE2-NEXT: ldr q1, [x1]
+; SVE2-NEXT: ldr q2, [x2]
+; SVE2-NEXT: fmlalb z0.s, z1.h, z2.h
+; SVE2-NEXT: fmlalt z0.s, z1.h, z2.h
; SVE2-NEXT: str q0, [x0]
; SVE2-NEXT: ret
;
@@ -216,14 +210,12 @@ entry:
define <4 x float> @fixed_fdot_wide(<4 x float> %acc, <8 x half> %a, <8 x half> %b) {
; SVE2-LABEL: fixed_fdot_wide:
; SVE2: // %bb.0: // %entry
-; SVE2-NEXT: fcvtl v3.4s, v1.4h
-; SVE2-NEXT: fcvtl v4.4s, v2.4h
-; SVE2-NEXT: fcvtl2 v1.4s, v1.8h
-; SVE2-NEXT: fcvtl2 v2.4s, v2.8h
-; SVE2-NEXT: fmul v3.4s, v3.4s, v4.4s
-; SVE2-NEXT: fmul v1.4s, v1.4s, v2.4s
-; SVE2-NEXT: fadd v0.4s, v0.4s, v3.4s
-; SVE2-NEXT: fadd v0.4s, v0.4s, v1.4s
+; SVE2-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE2-NEXT: // kill: def $q2 killed $q2 def $z2
+; SVE2-NEXT: // kill: def $q1 killed $q1 def $z1
+; SVE2-NEXT: fmlalb z0.s, z1.h, z2.h
+; SVE2-NEXT: fmlalt z0.s, z1.h, z2.h
+; SVE2-NEXT: // kill: def $q0 killed $q0 killed $z0
; SVE2-NEXT: ret
;
; SVE2P1-LABEL: fixed_fdot_wide:
@@ -245,12 +237,12 @@ entry:
define <2 x float> @fixed_fdot(<2 x float> %acc, <4 x half> %a, <4 x half> %b) {
; SVE2-LABEL: fixed_fdot:
; SVE2: // %bb.0: // %entry
-; SVE2-NEXT: fcvtl v1.4s, v1.4h
-; SVE2-NEXT: fcvtl v2.4s, v2.4h
-; SVE2-NEXT: fmul v1.4s, v1.4s, v2.4s
-; SVE2-NEXT: fadd v0.2s, v0.2s, v1.2s
-; SVE2-NEXT: ext v1.16b, v1.16b, v1.16b, #8
-; SVE2-NEXT: fadd v0.2s, v1.2s, v0.2s
+; SVE2-NEXT: // kill: def $d0 killed $d0 def $z0
+; SVE2-NEXT: // kill: def $d2 killed $d2 def $z2
+; SVE2-NEXT: // kill: def $d1 killed $d1 def $z1
+; SVE2-NEXT: fmlalb z0.s, z1.h, z2.h
+; SVE2-NEXT: fmlalt z0.s, z1.h, z2.h
+; SVE2-NEXT: // kill: def $d0 killed $d0 killed $z0
; SVE2-NEXT: ret
;
; SVE2P1-LABEL: fixed_fdot:
>From a8c608c896201cc03ab232d77093b8aad0ac834d Mon Sep 17 00:00:00 2001
From: Will Froom <willfroom at google.com>
Date: Wed, 18 Mar 2026 11:28:14 +0000
Subject: [PATCH 27/33] [mlir][vector] Use non-native runner in gather.mlir
test (#187243)
Fix after https://github.com/llvm/llvm-project/pull/187071
---
mlir/test/Integration/Dialect/Vector/CPU/gather.mlir | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir b/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir
index daf641d03eb75..110a46e2d89d8 100644
--- a/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir
+++ b/mlir/test/Integration/Dialect/Vector/CPU/gather.mlir
@@ -1,6 +1,6 @@
// DEFINE: %{entry_point} = main
// DEFINE: %{run} = mlir-runner -e entry -entry-point-result=void \
-// DEFINE: -shared-libs=%native_mlir_runner_utils,%native_mlir_c_runner_utils
+// DEFINE: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils
/// TEST 1. Verify default compilation (direct lowering of `vector.gather` to LLVM)
// DEFINE: %{compile} = mlir-opt %s -test-lower-to-llvm
>From 0a6abaaedb957fa97617e8c0c3a8d8cc3befed41 Mon Sep 17 00:00:00 2001
From: google-llvm-bazel-bot <google-bazel-bot at google.com>
Date: Wed, 18 Mar 2026 04:32:21 -0700
Subject: [PATCH 28/33] [Bazel] Fixes c1f6fd2 (#187146)
This fixes c1f6fd24aa637d6aadb72aa08bf3d8a14c961ed2.
---
.../bazel/llvm-project-overlay/clang/BUILD.bazel | 15 +++++++++++++++
.../clang/unittests/BUILD.bazel | 1 +
2 files changed, 16 insertions(+)
diff --git a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
index e18f5b68b9921..be35bf2fa804a 100644
--- a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
@@ -2610,6 +2610,21 @@ cc_library(
],
)
+cc_library(
+ name = "scalable_static_analysis_analyses",
+ srcs = glob([
+ "lib/ScalableStaticAnalysisFramework/Analyses/**/*.cpp",
+ ]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Analyses/**/*.h"]),
+ deps = [
+ ":analysis",
+ ":ast",
+ ":basic",
+ ":scalable_static_analysis_core",
+ "//llvm:Support",
+ ],
+)
+
cc_library(
name = "scalable_static_analysis_frontend",
srcs = glob([
diff --git a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
index 8a52a28032bb6..1fb1089165478 100644
--- a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
@@ -795,6 +795,7 @@ cc_test(
"//clang:basic",
"//clang:frontend",
"//clang:lex",
+ "//clang:scalable_static_analysis_analyses",
"//clang:scalable_static_analysis_core",
"//clang:scalable_static_analysis_frontend",
"//clang:support",
>From d04c93393cf538a81e3c3e4babcb732cc0a947c1 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Wed, 18 Mar 2026 12:40:13 +0100
Subject: [PATCH 29/33] [Clang][NFC] Drop uses of BranchInst (#187242)
---
clang/lib/CodeGen/CGClass.cpp | 2 +-
clang/lib/CodeGen/CGCleanup.cpp | 40 +++++++++++++--------------
clang/lib/CodeGen/CGException.cpp | 7 ++---
clang/lib/CodeGen/CGExpr.cpp | 2 +-
clang/lib/CodeGen/CGStmt.cpp | 6 ++--
clang/lib/CodeGen/CodeGenFunction.cpp | 7 ++---
clang/lib/CodeGen/EHScopeStack.h | 2 +-
7 files changed, 31 insertions(+), 35 deletions(-)
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 26a7f08f5cfc6..6572009fc6003 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -2174,7 +2174,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(
// because of GCC extensions that permit zero-length arrays. There
// are probably legitimate places where we could assume that this
// doesn't happen, but it's not clear that it's worth it.
- llvm::BranchInst *zeroCheckBranch = nullptr;
+ llvm::CondBrInst *zeroCheckBranch = nullptr;
// Optimize for a constant count.
llvm::ConstantInt *constantCount = dyn_cast<llvm::ConstantInt>(numElements);
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 28ac9bf396356..3d242bec73126 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -346,7 +346,7 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF,
createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex),
CGF.getNormalCleanupDestSlot(),
Fixup.InitialBranch->getIterator(), CGF);
- Fixup.InitialBranch->setSuccessor(0, CleanupEntry);
+ Fixup.InitialBranch->setSuccessor(CleanupEntry);
}
// Don't add this case to the switch statement twice.
@@ -369,8 +369,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF,
llvm::Instruction *Term = Block->getTerminator();
assert(Term && "can't transition block without terminator");
- if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
- assert(Br->isUnconditional());
+ if (llvm::UncondBrInst *Br = dyn_cast<llvm::UncondBrInst>(Term)) {
auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(),
"cleanup.dest", Term->getIterator(), CGF);
llvm::SwitchInst *Switch =
@@ -530,9 +529,10 @@ static llvm::BasicBlock *SimplifyCleanupEntry(CodeGenFunction &CGF,
llvm::BasicBlock *Pred = Entry->getSinglePredecessor();
if (!Pred) return Entry;
- llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Pred->getTerminator());
- if (!Br || Br->isConditional()) return Entry;
- assert(Br->getSuccessor(0) == Entry);
+ llvm::UncondBrInst *Br = dyn_cast<llvm::UncondBrInst>(Pred->getTerminator());
+ if (!Br)
+ return Entry;
+ assert(Br->getSuccessor() == Entry);
// If we were previously inserting at the end of the cleanup entry
// block, we'll need to continue inserting at the end of the
@@ -591,9 +591,9 @@ static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
// an unconditional branch or a switch.
llvm::Instruction *Term = Exit->getTerminator();
- if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
- assert(Br->isUnconditional() && Br->getSuccessor(0) == From);
- Br->setSuccessor(0, To);
+ if (llvm::UncondBrInst *Br = dyn_cast<llvm::UncondBrInst>(Term)) {
+ assert(Br->getSuccessor() == From);
+ Br->setSuccessor(To);
} else {
llvm::SwitchInst *Switch = cast<llvm::SwitchInst>(Term);
for (unsigned I = 0, E = Switch->getNumSuccessors(); I != E; ++I)
@@ -626,8 +626,8 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF,
llvm::SwitchInst *si = cast<llvm::SwitchInst>(use.getUser());
if (si->getNumCases() == 1 && si->getDefaultDest() == unreachableBB) {
// Replace the switch with a branch.
- llvm::BranchInst::Create(si->case_begin()->getCaseSuccessor(),
- si->getIterator());
+ llvm::UncondBrInst::Create(si->case_begin()->getCaseSuccessor(),
+ si->getIterator());
// The switch operand is a load from the cleanup-dest alloca.
llvm::LoadInst *condition = cast<llvm::LoadInst>(si->getCondition());
@@ -903,13 +903,13 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
}
llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0);
- InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter));
+ InstsToAppend.push_back(llvm::UncondBrInst::Create(BranchAfter));
- // Build a switch-out if we need it:
- // - if there are branch-afters threaded through the scope
- // - if fall-through is a branch-after
- // - if there are fixups that have nowhere left to go and
- // so must be immediately resolved
+ // Build a switch-out if we need it:
+ // - if there are branch-afters threaded through the scope
+ // - if fall-through is a branch-after
+ // - if there are fixups that have nowhere left to go and
+ // so must be immediately resolved
} else if (Scope.getNumBranchAfters() ||
(HasFallthrough && !FallthroughIsBranchThrough) ||
(HasFixups && !HasEnclosingCleanups)) {
@@ -950,7 +950,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
} else {
// We should always have a branch-through destination in this case.
assert(BranchThroughDest);
- InstsToAppend.push_back(llvm::BranchInst::Create(BranchThroughDest));
+ InstsToAppend.push_back(llvm::UncondBrInst::Create(BranchThroughDest));
}
// IV. Pop the cleanup and emit it.
@@ -975,7 +975,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex),
getNormalCleanupDestSlot(),
Fixup.InitialBranch->getIterator(), *this);
- Fixup.InitialBranch->setSuccessor(0, NormalEntry);
+ Fixup.InitialBranch->setSuccessor(NormalEntry);
}
Fixup.OptimisticBranchBlock = NormalExit;
}
@@ -1117,7 +1117,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
return;
// Create the branch.
- llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock());
+ llvm::UncondBrInst *BI = Builder.CreateBr(Dest.getBlock());
addInstToCurrentSourceAtom(BI, nullptr);
// Calculate the innermost active normal cleanup.
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 1437bc2d32159..7559727721496 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1325,11 +1325,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
// we follow the false destination for each of the cond branches to reach
// the rethrow block.
llvm::BasicBlock *RethrowBlock = WasmCatchStartBlock;
- while (llvm::Instruction *TI = RethrowBlock->getTerminator()) {
- auto *BI = cast<llvm::BranchInst>(TI);
- assert(BI->isConditional());
- RethrowBlock = BI->getSuccessor(1);
- }
+ while (llvm::Instruction *TI = RethrowBlock->getTerminator())
+ RethrowBlock = cast<llvm::CondBrInst>(TI)->getSuccessor(1);
assert(RethrowBlock != WasmCatchStartBlock && RethrowBlock->empty());
Builder.SetInsertPoint(RethrowBlock);
llvm::Function *RethrowInCatchFn =
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 88b2b6b3c33fb..23802cdeb4811 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4287,7 +4287,7 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
llvm::BasicBlock *Cont = createBasicBlock("cfi.cont");
llvm::BasicBlock *CheckBB = createBasicBlock("cfi.slowpath");
- llvm::BranchInst *BI = Builder.CreateCondBr(Cond, Cont, CheckBB);
+ llvm::CondBrInst *BI = Builder.CreateCondBr(Cond, Cont, CheckBB);
llvm::MDBuilder MDHelper(getLLVMContext());
llvm::MDNode *Node = MDHelper.createLikelyBranchWeights();
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index ad31ecc75b01e..a923002bec9b6 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -616,7 +616,7 @@ CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
}
void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {
- llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
+ llvm::UncondBrInst *BI = dyn_cast<llvm::UncondBrInst>(BB->getTerminator());
// If there is a cleanup stack, then we it isn't worth trying to
// simplify this block (we would need to remove it from the scope map
@@ -625,14 +625,14 @@ void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {
return;
// Can only simplify direct branches.
- if (!BI || !BI->isUnconditional())
+ if (!BI)
return;
// Can only simplify empty blocks.
if (BI->getIterator() != BB->begin())
return;
- BB->replaceAllUsesWith(BI->getSuccessor(0));
+ BB->replaceAllUsesWith(BI->getSuccessor());
BI->eraseFromParent();
BB->eraseFromParent();
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 81b293fe5fe89..a64cec801a173 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -326,10 +326,9 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
// branch then we can just put the code in that block instead. This
// cleans up functions which started with a unified return block.
if (ReturnBlock.getBlock()->hasOneUse()) {
- llvm::BranchInst *BI =
- dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin());
- if (BI && BI->isUnconditional() &&
- BI->getSuccessor(0) == ReturnBlock.getBlock()) {
+ auto *BI =
+ dyn_cast<llvm::UncondBrInst>(*ReturnBlock.getBlock()->user_begin());
+ if (BI && BI->getSuccessor(0) == ReturnBlock.getBlock()) {
// Record/return the DebugLoc of the simple 'return' expression to be used
// later by the actual 'ret' instruction.
llvm::DebugLoc Loc = BI->getDebugLoc();
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index 2dcb75556c4e5..b9b8021191d62 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -49,7 +49,7 @@ struct BranchFixup {
unsigned DestinationIndex;
/// The initial branch of the fixup.
- llvm::BranchInst *InitialBranch;
+ llvm::UncondBrInst *InitialBranch;
};
template <class T> struct InvariantValue {
>From d2d16e2851dbef5502128a02e93d4407fe6e940d Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Wed, 18 Mar 2026 11:53:01 +0000
Subject: [PATCH 30/33] [AArch64][llvm] Make SBZ/SBO insns warn not fail when
disassembling (#187068)
Some instructions in the Arm ARM have bits which are marked as "Should
Be One" or "Should Be Zero", and they're marked as "Constrained
Unpredictable" as to what should happen if they're not.
This is to improve hardware decode efficiency. In all the cases where
this occurs, it's an instruction which in all other respects is closely
related to an adjacent instruction in the encoding space (for example a
similar load or store) but doesn't require one of the variable fields,
usually a register field. These fields are then defined as SBZ or SBO.
If one of these instructions didn't have the bits set to SBZ or SBO,
then the instruction would fail to disassemble. We had missed adding
`Unpredictable` to a few of these, and they would fail rather than
warn.
Update these AArch64 instructions to treat `Unpredictable` bitfields as
soft-fails with a warning, and add a comprehensive disassembler
regression
test that checks all instructions which use `Unpredictable`.
The new tests check that `llvm-mc` emits a "potentially undefined
instruction encoding" warning, and verifies that the disassembler still
produces the canonical instruction spelling and encoding.
This keeps the behaviour consistent for users across SBO and SBZ
style reserved fields instead of rejecting encodings that should
disassemble with a warning.
---
.../lib/Target/AArch64/AArch64InstrFormats.td | 6 +
.../AArch64/reserved-bits-softfail.txt | 563 ++++++++++++++++++
2 files changed, 569 insertions(+)
create mode 100644 llvm/test/MC/Disassembler/AArch64/reserved-bits-softfail.txt
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 5fdb9814cc2e8..43727188a06d0 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2206,6 +2206,7 @@ class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
bits<5> Rt;
let Inst{31-30} = sz;
let Inst{29-10} = 0b11100010111111110000;
+ let Unpredictable{20-16} = 0b11111;
let Inst{9-5} = Rn;
let Inst{4-0} = Rt;
}
@@ -5206,6 +5207,8 @@ class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
bits<5> Rt;
bits<5> Rn;
let Inst{20-16} = Ws;
+ let Inst{14-10} = 0b11111;
+ let Unpredictable{14-10} = 0b11111;
let Inst{9-5} = Rn;
let Inst{4-0} = Rt;
@@ -12846,6 +12849,7 @@ class MOPSGoMemorySetTagging<bits<2> opcode, bit op1, bit op2, bit op3, string a
"\t[$Rd]!, $Rn!", 1, opcode, op1, op2, op3, asm> {
// No `Rm` operand, as all bits must be set to 1
let Inst{20-16} = 0b11111;
+ let Unpredictable{20-16} = 0b11111;
let DecoderMethod = "DecodeSETMemGoOpInstruction";
}
@@ -13629,6 +13633,7 @@ class TCHANGEImmInst<string asm, bit isB> : I<
let Inst{18} = isB;
let Inst{17} = nb;
let Inst{16-12} = 0b00000;
+ let Unpredictable{16-12} = 0b11111;
let Inst{11-5} = imm;
let Inst{4-0} = Xd;
}
@@ -13642,6 +13647,7 @@ class TENTERInst<string asm> : I<
let Inst{31-18} = 0b11010100111000;
let Inst{17} = nb;
let Inst{16-12} = 0b00000;
+ let Unpredictable{16-12} = 0b11111;
let Inst{11-5} = imm;
let Inst{4-0} = 0b00000;
}
diff --git a/llvm/test/MC/Disassembler/AArch64/reserved-bits-softfail.txt b/llvm/test/MC/Disassembler/AArch64/reserved-bits-softfail.txt
new file mode 100644
index 0000000000000..ae361854e1f7c
--- /dev/null
+++ b/llvm/test/MC/Disassembler/AArch64/reserved-bits-softfail.txt
@@ -0,0 +1,563 @@
+# RUN: llvm-mc -triple=aarch64 -mattr=+all -disassemble -show-encoding < %s 2>&1 | FileCheck --check-prefix=WARN %s
+# RUN: llvm-mc -triple=aarch64 -mattr=+all -disassemble -show-encoding < %s 2>/dev/null | FileCheck --check-prefix=DIS %s
+
+# Fill in the "unpredictable" bits (should-be-one or should-be-zero to
+# avoid "constrained unpredictable" according to the Arm ARM) with these
+# bit patterns in the hex encodings below:
+#
+# field(s) pattern
+# {20-16} 0b10110
+# {16-12} 0b10110
+# {14-10} 0b10110
+# {11-8} 0b0101
+# {15-14} 0b10
+#
+# This verifies every Unpredictable encoding soft-fails for non-canonical
+# values without relying on all-zero or all-one test cases.
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xc0,0xb6,0x38]
+# WARN-NEXT: ^
+# ldaprb w0, [x1]
+[0x20,0xc0,0xb6,0x38]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xc0,0xb6,0x78]
+# WARN-NEXT: ^
+# ldaprh w0, [x1]
+[0x20,0xc0,0xb6,0x78]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xc0,0xb6,0xb8]
+# WARN-NEXT: ^
+# ldapr w0, [x1]
+[0x20,0xc0,0xb6,0xb8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xc0,0xb6,0xf8]
+# WARN-NEXT: ^
+# ldapr x0, [x1]
+[0x20,0xc0,0xb6,0xf8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x41,0x58,0x43,0x9b]
+# WARN-NEXT: ^
+# smulh x1, x2, x3
+[0x41,0x58,0x43,0x9b]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x41,0x58,0xc3,0x9b]
+# WARN-NEXT: ^
+# umulh x1, x2, x3
+[0x41,0x58,0xc3,0x9b]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x84,0x80,0x91]
+# WARN-NEXT: ^
+# addg x0, x1, #0, #1
+[0x20,0x84,0x80,0x91]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x84,0x80,0xd1]
+# WARN-NEXT: ^
+# subg x0, x1, #0, #1
+[0x20,0x84,0x80,0xd1]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0xd6,0x08]
+# WARN-NEXT: ^
+# ldarb w0, [x1]
+[0x20,0xd8,0xd6,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0xd6,0x48]
+# WARN-NEXT: ^
+# ldarh w0, [x1]
+[0x20,0xd8,0xd6,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0xd6,0x88]
+# WARN-NEXT: ^
+# ldar w0, [x1]
+[0x20,0xd8,0xd6,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0xd6,0xc8]
+# WARN-NEXT: ^
+# ldar x0, [x1]
+[0x20,0xd8,0xd6,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0xd6,0x08]
+# WARN-NEXT: ^
+# ldlarb w0, [x1]
+[0x20,0x58,0xd6,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0xd6,0x48]
+# WARN-NEXT: ^
+# ldlarh w0, [x1]
+[0x20,0x58,0xd6,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0xd6,0x88]
+# WARN-NEXT: ^
+# ldlar w0, [x1]
+[0x20,0x58,0xd6,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0xd6,0xc8]
+# WARN-NEXT: ^
+# ldlar x0, [x1]
+[0x20,0x58,0xd6,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x56,0x08]
+# WARN-NEXT: ^
+# ldaxrb w0, [x1]
+[0x20,0xd8,0x56,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x56,0x48]
+# WARN-NEXT: ^
+# ldaxrh w0, [x1]
+[0x20,0xd8,0x56,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x56,0x88]
+# WARN-NEXT: ^
+# ldaxr w0, [x1]
+[0x20,0xd8,0x56,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x56,0xc8]
+# WARN-NEXT: ^
+# ldaxr x0, [x1]
+[0x20,0xd8,0x56,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x56,0x08]
+# WARN-NEXT: ^
+# ldxrb w0, [x1]
+[0x20,0x58,0x56,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x56,0x48]
+# WARN-NEXT: ^
+# ldxrh w0, [x1]
+[0x20,0x58,0x56,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x56,0x88]
+# WARN-NEXT: ^
+# ldxr w0, [x1]
+[0x20,0x58,0x56,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x56,0xc8]
+# WARN-NEXT: ^
+# ldxr x0, [x1]
+[0x20,0x58,0x56,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x96,0x08]
+# WARN-NEXT: ^
+# stlrb w0, [x1]
+[0x20,0xd8,0x96,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x96,0x48]
+# WARN-NEXT: ^
+# stlrh w0, [x1]
+[0x20,0xd8,0x96,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x96,0x88]
+# WARN-NEXT: ^
+# stlr w0, [x1]
+[0x20,0xd8,0x96,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x96,0xc8]
+# WARN-NEXT: ^
+# stlr x0, [x1]
+[0x20,0xd8,0x96,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x96,0x08]
+# WARN-NEXT: ^
+# stllrb w0, [x1]
+[0x20,0x58,0x96,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x96,0x48]
+# WARN-NEXT: ^
+# stllrh w0, [x1]
+[0x20,0x58,0x96,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x96,0x88]
+# WARN-NEXT: ^
+# stllr w0, [x1]
+[0x20,0x58,0x96,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x96,0xc8]
+# WARN-NEXT: ^
+# stllr x0, [x1]
+[0x20,0x58,0x96,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x88,0x76,0x88]
+# WARN-NEXT: ^
+# ldaxp w0, w2, [x1]
+[0x20,0x88,0x76,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x88,0x76,0xc8]
+# WARN-NEXT: ^
+# ldaxp x0, x2, [x1]
+[0x20,0x88,0x76,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x08,0x76,0x88]
+# WARN-NEXT: ^
+# ldxp w0, w2, [x1]
+[0x20,0x08,0x76,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x08,0x76,0xc8]
+# WARN-NEXT: ^
+# ldxp x0, x2, [x1]
+[0x20,0x08,0x76,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x56,0x89]
+# WARN-NEXT: ^
+# ldtxr w0, [x1]
+[0x20,0x58,0x56,0x89]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x56,0xc9]
+# WARN-NEXT: ^
+# ldtxr x0, [x1]
+[0x20,0x58,0x56,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x56,0x89]
+# WARN-NEXT: ^
+# ldatxr w0, [x1]
+[0x20,0xd8,0x56,0x89]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x56,0xc9]
+# WARN-NEXT: ^
+# ldatxr x0, [x1]
+[0x20,0xd8,0x56,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x02,0x89]
+# WARN-NEXT: ^
+# sttxr w2, w0, [x1]
+[0x20,0x58,0x02,0x89]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x02,0xc9]
+# WARN-NEXT: ^
+# sttxr w2, x0, [x1]
+[0x20,0x58,0x02,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x02,0x89]
+# WARN-NEXT: ^
+# stltxr w2, w0, [x1]
+[0x20,0xd8,0x02,0x89]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x02,0xc9]
+# WARN-NEXT: ^
+# stltxr w2, x0, [x1]
+[0x20,0xd8,0x02,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x02,0x08]
+# WARN-NEXT: ^
+# stlxrb w2, w0, [x1]
+[0x20,0xd8,0x02,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x02,0x48]
+# WARN-NEXT: ^
+# stlxrh w2, w0, [x1]
+[0x20,0xd8,0x02,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x02,0x88]
+# WARN-NEXT: ^
+# stlxr w2, w0, [x1]
+[0x20,0xd8,0x02,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0xd8,0x02,0xc8]
+# WARN-NEXT: ^
+# stlxr w2, x0, [x1]
+[0x20,0xd8,0x02,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x02,0x08]
+# WARN-NEXT: ^
+# stxrb w2, w0, [x1]
+[0x20,0x58,0x02,0x08]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x02,0x48]
+# WARN-NEXT: ^
+# stxrh w2, w0, [x1]
+[0x20,0x58,0x02,0x48]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x02,0x88]
+# WARN-NEXT: ^
+# stxr w2, w0, [x1]
+[0x20,0x58,0x02,0x88]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x20,0x58,0x02,0xc8]
+# WARN-NEXT: ^
+# stxr w2, x0, [x1]
+[0x20,0x58,0x02,0xc8]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x1f,0x45,0x00,0xd5]
+# WARN-NEXT: ^
+# cfinv
+[0x1f,0x45,0x00,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x3f,0x45,0x00,0xd5]
+# WARN-NEXT: ^
+# xaflag
+[0x3f,0x45,0x00,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x5f,0x45,0x00,0xd5]
+# WARN-NEXT: ^
+# axflag
+[0x5f,0x45,0x00,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0xff,0x35,0x03,0xd5]
+# WARN-NEXT: ^
+# sb
+[0xff,0x35,0x03,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x22,0x58,0x80,0xc9]
+# WARN-NEXT: ^
+# cast x0, x2, [x1]
+[0x22,0x58,0x80,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x22,0xd8,0x80,0xc9]
+# WARN-NEXT: ^
+# caslt x0, x2, [x1]
+[0x22,0xd8,0x80,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x22,0x58,0xc0,0xc9]
+# WARN-NEXT: ^
+# casat x0, x2, [x1]
+[0x22,0x58,0xc0,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x22,0xd8,0xc0,0xc9]
+# WARN-NEXT: ^
+# casalt x0, x2, [x1]
+[0x22,0xd8,0xc0,0xc9]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x00,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgop [x3]!, x2!
+[0x43,0x00,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x40,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgom [x3]!, x2!
+[0x43,0x40,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x80,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgoe [x3]!, x2!
+[0x43,0x80,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x20,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgopn [x3]!, x2!
+[0x43,0x20,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x60,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgomn [x3]!, x2!
+[0x43,0x60,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0xa0,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgoen [x3]!, x2!
+[0x43,0xa0,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x10,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgopt [x3]!, x2!
+[0x43,0x10,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x50,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgomt [x3]!, x2!
+[0x43,0x50,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x90,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgoet [x3]!, x2!
+[0x43,0x90,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x30,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgoptn [x3]!, x2!
+[0x43,0x30,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0x70,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgomtn [x3]!, x2!
+[0x43,0x70,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x43,0xb0,0xd6,0x1d]
+# WARN-NEXT: ^
+# setgoetn [x3]!, x2!
+[0x43,0xb0,0xd6,0x1d]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x21,0x61,0x95,0xd5]
+# WARN-NEXT: ^
+# tchangeb x1, #9
+[0x21,0x61,0x95,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x21,0x61,0x97,0xd5]
+# WARN-NEXT: ^
+# tchangeb x1, #9, nb
+[0x21,0x61,0x97,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x61,0x60,0x91,0xd5]
+# WARN-NEXT: ^
+# tchangef x1, #3
+[0x61,0x60,0x91,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x61,0x60,0x93,0xd5]
+# WARN-NEXT: ^
+# tchangef x1, #3, nb
+[0x61,0x60,0x93,0xd5]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x00,0x64,0xe1,0xd4]
+# WARN-NEXT: ^
+# tenter #32
+[0x00,0x64,0xe1,0xd4]
+
+# WARN: warning: potentially undefined instruction encoding
+# WARN-NEXT: [0x00,0x64,0xe3,0xd4]
+# WARN-NEXT: ^
+# tenter #32, nb
+[0x00,0x64,0xe3,0xd4]
+
+# DIS-DAG: ldaprb w0, [x1] // encoding: [0x20,0xc0,0xbf,0x38]
+# DIS-DAG: ldaprh w0, [x1] // encoding: [0x20,0xc0,0xbf,0x78]
+# DIS-DAG: ldapr w0, [x1] // encoding: [0x20,0xc0,0xbf,0xb8]
+# DIS-DAG: ldapr x0, [x1] // encoding: [0x20,0xc0,0xbf,0xf8]
+# DIS-DAG: smulh x1, x2, x3 // encoding: [0x41,0x7c,0x43,0x9b]
+# DIS-DAG: umulh x1, x2, x3 // encoding: [0x41,0x7c,0xc3,0x9b]
+# DIS-DAG: addg x0, x1, #0, #1 // encoding: [0x20,0x04,0x80,0x91]
+# DIS-DAG: subg x0, x1, #0, #1 // encoding: [0x20,0x04,0x80,0xd1]
+# DIS-DAG: ldarb w0, [x1] // encoding: [0x20,0xfc,0xdf,0x08]
+# DIS-DAG: ldarh w0, [x1] // encoding: [0x20,0xfc,0xdf,0x48]
+# DIS-DAG: ldar w0, [x1] // encoding: [0x20,0xfc,0xdf,0x88]
+# DIS-DAG: ldar x0, [x1] // encoding: [0x20,0xfc,0xdf,0xc8]
+# DIS-DAG: ldlarb w0, [x1] // encoding: [0x20,0x7c,0xdf,0x08]
+# DIS-DAG: ldlarh w0, [x1] // encoding: [0x20,0x7c,0xdf,0x48]
+# DIS-DAG: ldlar w0, [x1] // encoding: [0x20,0x7c,0xdf,0x88]
+# DIS-DAG: ldlar x0, [x1] // encoding: [0x20,0x7c,0xdf,0xc8]
+# DIS-DAG: ldaxrb w0, [x1] // encoding: [0x20,0xfc,0x5f,0x08]
+# DIS-DAG: ldaxrh w0, [x1] // encoding: [0x20,0xfc,0x5f,0x48]
+# DIS-DAG: ldaxr w0, [x1] // encoding: [0x20,0xfc,0x5f,0x88]
+# DIS-DAG: ldaxr x0, [x1] // encoding: [0x20,0xfc,0x5f,0xc8]
+# DIS-DAG: ldxrb w0, [x1] // encoding: [0x20,0x7c,0x5f,0x08]
+# DIS-DAG: ldxrh w0, [x1] // encoding: [0x20,0x7c,0x5f,0x48]
+# DIS-DAG: ldxr w0, [x1] // encoding: [0x20,0x7c,0x5f,0x88]
+# DIS-DAG: ldxr x0, [x1] // encoding: [0x20,0x7c,0x5f,0xc8]
+# DIS-DAG: stlrb w0, [x1] // encoding: [0x20,0xfc,0x9f,0x08]
+# DIS-DAG: stlrh w0, [x1] // encoding: [0x20,0xfc,0x9f,0x48]
+# DIS-DAG: stlr w0, [x1] // encoding: [0x20,0xfc,0x9f,0x88]
+# DIS-DAG: stlr x0, [x1] // encoding: [0x20,0xfc,0x9f,0xc8]
+# DIS-DAG: stllrb w0, [x1] // encoding: [0x20,0x7c,0x9f,0x08]
+# DIS-DAG: stllrh w0, [x1] // encoding: [0x20,0x7c,0x9f,0x48]
+# DIS-DAG: stllr w0, [x1] // encoding: [0x20,0x7c,0x9f,0x88]
+# DIS-DAG: stllr x0, [x1] // encoding: [0x20,0x7c,0x9f,0xc8]
+# DIS-DAG: ldaxp w0, w2, [x1] // encoding: [0x20,0x88,0x7f,0x88]
+# DIS-DAG: ldaxp x0, x2, [x1] // encoding: [0x20,0x88,0x7f,0xc8]
+# DIS-DAG: ldxp w0, w2, [x1] // encoding: [0x20,0x08,0x7f,0x88]
+# DIS-DAG: ldxp x0, x2, [x1] // encoding: [0x20,0x08,0x7f,0xc8]
+# DIS-DAG: ldtxr w0, [x1] // encoding: [0x20,0x7c,0x5f,0x89]
+# DIS-DAG: ldtxr x0, [x1] // encoding: [0x20,0x7c,0x5f,0xc9]
+# DIS-DAG: ldatxr w0, [x1] // encoding: [0x20,0xfc,0x5f,0x89]
+# DIS-DAG: ldatxr x0, [x1] // encoding: [0x20,0xfc,0x5f,0xc9]
+# DIS-DAG: sttxr w2, w0, [x1] // encoding: [0x20,0x7c,0x02,0x89]
+# DIS-DAG: sttxr w2, x0, [x1] // encoding: [0x20,0x7c,0x02,0xc9]
+# DIS-DAG: stltxr w2, w0, [x1] // encoding: [0x20,0xfc,0x02,0x89]
+# DIS-DAG: stltxr w2, x0, [x1] // encoding: [0x20,0xfc,0x02,0xc9]
+# DIS-DAG: stlxrb w2, w0, [x1] // encoding: [0x20,0xfc,0x02,0x08]
+# DIS-DAG: stlxrh w2, w0, [x1] // encoding: [0x20,0xfc,0x02,0x48]
+# DIS-DAG: stlxr w2, w0, [x1] // encoding: [0x20,0xfc,0x02,0x88]
+# DIS-DAG: stlxr w2, x0, [x1] // encoding: [0x20,0xfc,0x02,0xc8]
+# DIS-DAG: stxrb w2, w0, [x1] // encoding: [0x20,0x7c,0x02,0x08]
+# DIS-DAG: stxrh w2, w0, [x1] // encoding: [0x20,0x7c,0x02,0x48]
+# DIS-DAG: stxr w2, w0, [x1] // encoding: [0x20,0x7c,0x02,0x88]
+# DIS-DAG: stxr w2, x0, [x1] // encoding: [0x20,0x7c,0x02,0xc8]
+# DIS-DAG: cfinv // encoding: [0x1f,0x40,0x00,0xd5]
+# DIS-DAG: xaflag // encoding: [0x3f,0x40,0x00,0xd5]
+# DIS-DAG: axflag // encoding: [0x5f,0x40,0x00,0xd5]
+# DIS-DAG: sb // encoding: [0xff,0x30,0x03,0xd5]
+# DIS-DAG: cast x0, x2, [x1] // encoding: [0x22,0x7c,0x80,0xc9]
+# DIS-DAG: caslt x0, x2, [x1] // encoding: [0x22,0xfc,0x80,0xc9]
+# DIS-DAG: casat x0, x2, [x1] // encoding: [0x22,0x7c,0xc0,0xc9]
+# DIS-DAG: casalt x0, x2, [x1] // encoding: [0x22,0xfc,0xc0,0xc9]
+# DIS-DAG: setgop [x3]!, x2! // encoding: [0x43,0x00,0xdf,0x1d]
+# DIS-DAG: setgom [x3]!, x2! // encoding: [0x43,0x40,0xdf,0x1d]
+# DIS-DAG: setgoe [x3]!, x2! // encoding: [0x43,0x80,0xdf,0x1d]
+# DIS-DAG: setgopn [x3]!, x2! // encoding: [0x43,0x20,0xdf,0x1d]
+# DIS-DAG: setgomn [x3]!, x2! // encoding: [0x43,0x60,0xdf,0x1d]
+# DIS-DAG: setgoen [x3]!, x2! // encoding: [0x43,0xa0,0xdf,0x1d]
+# DIS-DAG: setgopt [x3]!, x2! // encoding: [0x43,0x10,0xdf,0x1d]
+# DIS-DAG: setgomt [x3]!, x2! // encoding: [0x43,0x50,0xdf,0x1d]
+# DIS-DAG: setgoet [x3]!, x2! // encoding: [0x43,0x90,0xdf,0x1d]
+# DIS-DAG: setgoptn [x3]!, x2! // encoding: [0x43,0x30,0xdf,0x1d]
+# DIS-DAG: setgomtn [x3]!, x2! // encoding: [0x43,0x70,0xdf,0x1d]
+# DIS-DAG: setgoetn [x3]!, x2! // encoding: [0x43,0xb0,0xdf,0x1d]
+# DIS-DAG: tchangeb x1, #9 // encoding: [0x21,0x01,0x94,0xd5]
+# DIS-DAG: tchangeb x1, #9, nb // encoding: [0x21,0x01,0x96,0xd5]
+# DIS-DAG: tchangef x1, #3 // encoding: [0x61,0x00,0x90,0xd5]
+# DIS-DAG: tchangef x1, #3, nb // encoding: [0x61,0x00,0x92,0xd5]
+# DIS-DAG: tenter #32 // encoding: [0x00,0x04,0xe0,0xd4]
+# DIS-DAG: tenter #32, nb // encoding: [0x00,0x04,0xe2,0xd4]
>From 185b35610f2c17685eb2a72e6aa46f4c428956c9 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 18 Mar 2026 08:02:10 -0400
Subject: [PATCH 31/33] [OpenMP] Map const-qualified target map variables as
'to'. (#185918)
This patch updates the mapping kind for const-qualified variables
from`tofrom` to `to`, ensuring correct and standards-compliant mapping
semantics for const variables.
---
clang/lib/Sema/SemaOpenMP.cpp | 54 ++++-
clang/test/OpenMP/map_const_aggregate.cpp | 246 ++++++++++++++++++++++
2 files changed, 296 insertions(+), 4 deletions(-)
create mode 100644 clang/test/OpenMP/map_const_aggregate.cpp
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 34869e50b74ac..0d3c7fc4907a2 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3862,7 +3862,8 @@ static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
static OpenMPMapClauseKind
getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
- bool IsAggregateOrDeclareTarget) {
+ bool IsAggregateOrDeclareTarget,
+ bool HasConstQualifier) {
OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
switch (M) {
case OMPC_DEFAULTMAP_MODIFIER_alloc:
@@ -3897,7 +3898,10 @@ getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
// 1. the implicit behavior for aggregate is tofrom
// 2. it's a declare target link
if (IsAggregateOrDeclareTarget) {
- Kind = OMPC_MAP_tofrom;
+ if (HasConstQualifier)
+ Kind = OMPC_MAP_to;
+ else
+ Kind = OMPC_MAP_tofrom;
break;
}
llvm_unreachable("Unexpected defaultmap implicit behavior");
@@ -3906,6 +3910,36 @@ getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
return Kind;
}
+static bool hasNoMutableFields(const CXXRecordDecl *RD) {
+ for (const auto *FD : RD->fields()) {
+ if (FD->isMutable())
+ return false;
+ QualType FT = FD->getType();
+ while (FT->isArrayType())
+ FT = FT->getAsArrayTypeUnsafe()->getElementType();
+ if (const auto *NestedRD = FT->getAsCXXRecordDecl())
+ if (!hasNoMutableFields(NestedRD))
+ return false;
+ }
+ return true;
+}
+
+static bool hasConstQualifiedMappingType(QualType T) {
+ while (T->isArrayType())
+ T = T->getAsArrayTypeUnsafe()->getElementType();
+ if (!T.isConstQualified())
+ return false;
+ if (const auto *RD = T->getAsCXXRecordDecl())
+ // TODO : Per OpenMP 6.0 p299 lines 3-4, non-mutable members of a
+ // const-qualified struct should also be ignored for 'from'. This
+ // requires per-member mapping granularity via compiler-generated
+ // default mappers and a mechanism to ensure constness to the mapper.
+ // For now we conservatively treat any struct with mutable members as
+ // requiring full 'tofrom'.
+ return hasNoMutableFields(RD);
+ return true;
+}
+
namespace {
struct VariableImplicitInfo {
static const unsigned MapKindNum = OMPC_MAP_unknown;
@@ -4128,7 +4162,8 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
ImpInfo.Privates.insert(E);
} else {
OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
- M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
+ M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
+ hasConstQualifiedMappingType(E->getType()));
ImpInfo.Mappings[ClauseKind][Kind].insert(E);
}
}
@@ -4225,7 +4260,8 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
OpenMPDefaultmapClauseKind ClauseKind =
getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
- Modifier, /*IsAggregateOrDeclareTarget=*/true);
+ Modifier, /*IsAggregateOrDeclareTarget=*/true,
+ /*HasConstQualifier=*/false);
ImpInfo.Mappings[ClauseKind][Kind].insert(E);
return;
}
@@ -23498,6 +23534,16 @@ OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
}
MappableVarListInfo MVLI(VarList);
+ // Per OpenMP 6.0 p299 lines 3-4, a list item with the const specifier and
+ // no mutable members is ignored for 'from' clauses. A const-qualified
+ // variable cannot be modified on the device, so copying back to the host
+ // is unnecessary and potentially unsafe. Strip the FROM component:
+ // map(tofrom:) -> map(to:), map(from:) -> map(alloc:).
+ for (auto *E : VarList) {
+ if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
+ hasConstQualifiedMappingType(E->getType()))
+ MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
+ }
checkMappableExpressionList(SemaRef, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
MapperIdScopeSpec, MapperId, UnresolvedMappers,
MapType, Modifiers, IsMapTypeImplicit,
diff --git a/clang/test/OpenMP/map_const_aggregate.cpp b/clang/test/OpenMP/map_const_aggregate.cpp
new file mode 100644
index 0000000000000..fbb1c3a5abe60
--- /dev/null
+++ b/clang/test/OpenMP/map_const_aggregate.cpp
@@ -0,0 +1,246 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu \
+// RUN: -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+// RUN %clang_cc1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu \
+// RUN -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+// expected-no-diagnostics
+
+// Tests that const-qualified aggregates without mutable members are implicitly
+// mapped as 'to' instead of 'tofrom' under defaultmap(tofrom:aggregate) and
+// explicit map clauses. Structs that have mutable members, or that are
+// non-const, must continue to be mapped 'tofrom'.
+
+struct foo {
+ foo(int j) : i(j) {};
+ int i;
+};
+
+struct foo_mutable {
+ foo_mutable(int j) : i(j), m(0) {};
+ int i;
+ mutable int m;
+};
+
+// TODO: A const foo_mutable should ideally only copy back its mutable
+// member 'm' and ignore non-mutable member 'i' on a 'from' mapping, per
+// OpenMP 6.0 p299 lines 3-4. This requires per-member mapper generation
+// and is left for a follow-up patch.
+struct foo_nested {
+ foo_nested(int j) : inner(j), z(j) {};
+ foo inner;
+ const int z;
+};
+
+struct foo_nested_mutable {
+ foo_nested_mutable(int j) : inner(j), z(j) {};
+ foo_mutable inner; // has mutable member buried inside
+ const int z;
+};
+
+// CHECK: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 545, i64 288]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 547, i64 288]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 547, i64 288]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 545, i64 288]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [2 x i64] [i64 547, i64 288]
+// CHECK: @.offload_maptypes.10 = private unnamed_addr constant [2 x i64] [i64 545, i64 288]
+// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [2 x i64] [i64 33, i64 288]
+// CHECK: @.offload_maptypes.14 = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
+// CHECK: @.offload_maptypes.16 = private unnamed_addr constant [2 x i64] [i64 33, i64 288]
+// CHECK: @.offload_maptypes.18 = private unnamed_addr constant [1 x i64] [i64 2]
+// CHECK: @.offload_maptypes.20 = private unnamed_addr constant [1 x i64] [i64 2]
+// CHECK: @.offload_maptypes.22 = private unnamed_addr constant [1 x i64] [i64 2]
+// CHECK: @.offload_maptypes.24 = private unnamed_addr constant [3 x i64] [i64 545, i64 547, i64 288]
+// CHECK: @.offload_maptypes.26 = private unnamed_addr constant [2 x i64] [i64 545, i64 288]
+// CHECK: @.offload_maptypes.28 = private unnamed_addr constant [1 x i64] [i64 2]
+
+// ---------------------------------------------------------------------------
+// Implicit mapping tests (no explicit map clause, defaultmap governs)
+// ---------------------------------------------------------------------------
+
+// Const struct with no mutable members. Mapped as TO|TARGET_PARAM|IMPLICIT = 545.
+// LABEL: test_const_no_mutable
+// CHECK: store ptr @.offload_maptypes, ptr {{.*}}, align 8
+void test_const_no_mutable() {
+ const foo a(2);
+#pragma omp target
+ {
+ int x = a.i;
+ }
+}
+
+// Non-const struct. Mapped as TO|FROM|TARGET_PARAM|IMPLICIT = 547.
+// LABEL: define dso_local void @_Z13test_nonconstv
+// CHECK: store ptr @.offload_maptypes.2, ptr {{.*}}, align 8
+void test_nonconst() {
+ foo a(2);
+#pragma omp target
+ {
+ int x = a.i;
+ }
+}
+
+// Const struct with a mutable member. Mapped as TO|FROM|TARGET_PARAM|IMPLICIT = 547.
+// LABEL: define dso_local void @_Z23test_const_with_mutablev
+// CHECK: store ptr @.offload_maptypes.4, ptr {{.*}}, align 8
+void test_const_with_mutable() {
+ const foo_mutable a(2);
+#pragma omp target
+ {
+ a.m = 1;
+ }
+}
+
+// Const struct whose members are themselves all const and free of mutable
+// fields. Mapped as TO|TARGET_PARAM|IMPLICIT = 545.
+// LABEL: define dso_local void @_Z17test_const_nestedv() #0 {
+// CHECK: store ptr @.offload_maptypes.6, ptr {{.*}}, align 8
+void test_const_nested() {
+ const foo_nested a(2);
+#pragma omp target
+ {
+ int x = a.inner.i;
+ }
+}
+
+// Const array of a const-qualified struct type.
+// Mapped as TO|FROM|TARGET_PARAM|IMPLICIT = 547.
+// LABEL: define dso_local void @_Z30test_const_nested_with_mutablev
+// CHECK: store ptr @.offload_maptypes.8, ptr {{.*}}, align 8
+void test_const_nested_with_mutable() {
+ const foo_nested_mutable a(2);
+#pragma omp target
+ {
+ a.inner.m = 1;
+ }
+}
+
+// Const array of a const-qualified struct type.
+// Mapped as TO|TARGET_PARAM|IMPLICIT = 545.
+// LABEL: define dso_local void @_Z16test_const_arrayv
+// CHECK: store ptr @.offload_maptypes.10, ptr {{.*}}, align 8
+void test_const_array() {
+ const foo arr[4] = {1, 2, 3, 4};
+#pragma omp target
+ {
+ int x = arr[0].i;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Explicit map clause tests
+// ---------------------------------------------------------------------------
+
+// Explicit map(tofrom:) on a const struct. Mapped as TO|TARGET_PARAM = 33.
+// LABEL: define dso_local void @_Z27test_explicit_tofrom_const
+// CHECK: store ptr @.offload_maptypes.12, ptr {{.*}}, align 8
+void test_explicit_tofrom_const() {
+ const foo a(2);
+#pragma omp target map(tofrom:a)
+ {
+ int x = a.i;
+ }
+}
+
+// Explicit map(from:) on a const struct. The FROM clause is ignored.
+// Mapped as TARGET_PARAM = 32.
+// LABEL: define dso_local void @_Z24test_explicit_from_constv
+// CHECK: store ptr @.offload_maptypes.14, ptr {{.*}}, align 8
+void test_explicit_from_const() {
+ const foo a(2);
+#pragma omp target map(from:a)
+ {
+ int x = a.i;
+ }
+}
+
+// Explicit map(to:) on a const struct. Mapped as TO|TARGET_PARAM = 33.
+// LABEL: define dso_local void @_Z22test_explicit_to_constv()
+// CHECK: store ptr @.offload_maptypes.16, ptr {{.*}}, align 8
+void test_explicit_to_const() {
+ const foo a(2);
+#pragma omp target map(to:a)
+ {
+ int x = a.i;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// target update from tests
+// ---------------------------------------------------------------------------
+
+// target update from on a const struct with no mutable members. The FROM clause
+// is ignored. Mapped as FROM = 2.
+// LABEL: define dso_local void @_Z29test_target_update_from_constv
+// CHECK: call void @__tgt_target_data_update_mapper(ptr @1, i64 -1, i32 1, ptr %3, ptr %4, ptr @.offload_sizes.17, ptr @.offload_maptypes.18, ptr null, ptr null)
+void test_target_update_from_const() {
+ const foo a(2);
+#pragma omp target update from(a)
+}
+
+// target update from on a non-const struct. Mapped as FROM = 2.
+// LABEL: define dso_local void @_Z32test_target_update_from_nonconstv
+// CHECK: call void @__tgt_target_data_update_mapper(ptr @1, i64 -1, i32 1, ptr %3, ptr %4, ptr @.offload_sizes.19, ptr @.offload_maptypes.20, ptr null, ptr null)
+void test_target_update_from_nonconst() {
+ foo a(2);
+#pragma omp target update from(a)
+}
+
+// target update from on a const struct that has a mutable member. Mapped as FROM = 2.
+// LABEL: define dso_local void @_Z37test_target_update_from_const_mutablev
+// CHECK: call void @__tgt_target_data_update_mapper(ptr @1, i64 -1, i32 1, ptr %3, ptr %4, ptr @.offload_sizes.21, ptr @.offload_maptypes.22, ptr null, ptr null)
+void test_target_update_from_const_mutable() {
+ const foo_mutable a(2);
+#pragma omp target update from(a)
+}
+
+// ---------------------------------------------------------------------------
+// Combined tests
+// ---------------------------------------------------------------------------
+
+// Mixed region with one const and one non-const variable of the same struct
+// type. Each variable gets its own map type: const maps as
+// TO|TARGET_PARAM|IMPLICIT = 545, non-const maps as
+// TO|FROM|TARGET_PARAM|IMPLICIT = 547.
+// LABEL: define dso_local void @_Z10test_mixedv
+// CHECK: store ptr @.offload_maptypes.24, ptr {{.*}}, align 8
+void test_mixed() {
+ const foo ca(2);
+ foo ma(3);
+#pragma omp target
+ {
+ int x = ca.i;
+ ma.i = 99;
+ }
+}
+
+// Explicit defaultmap(tofrom:aggregate) directive on a const struct.
+// Mapped as TO|TARGET_PARAM|IMPLICIT = 545.
+// LABEL: define dso_local void @_Z31test_defaultmap_tofrom_explicitv
+// CHECK: store ptr @.offload_maptypes.26, ptr {{.*}}, align 8
+void test_defaultmap_tofrom_explicit() {
+ const foo a(2);
+#pragma omp target defaultmap(tofrom:aggregate)
+ {
+ int x = a.i;
+ }
+}
+
+// User-defined mapper on const struct — FROM must NOT be suppressed because the
+// mapper accesses non-const pointee data py[0:10].
+// Mapped as FROM = 2.
+// LABEL: define dso_local void @_Z30test_user_defined_mapper_constv
+// CHECK: call void @__tgt_target_data_update_mapper(ptr @1, i64 -1, i32 1, ptr {{.*}}, ptr {{.*}}, ptr @.offload_sizes.27, ptr @.offload_maptypes.28, ptr null, ptr {{.*}})
+int y[10];
+struct S {
+ int x;
+ int *py;
+};
+
+#pragma omp declare mapper(m1: const S s) map(alloc: s.x, s.py) map(from: s.py[0:10])
+
+void test_user_defined_mapper_const() {
+ int data[10] = {0};
+ const S s1 = {1, data};
+ #pragma omp target update from(mapper(m1): s1)
+}
>From 67921fa35e739cf91f1cc145591525972f4156d9 Mon Sep 17 00:00:00 2001
From: Dmitry Vasilyev <dvassiliev at accesssoftek.com>
Date: Wed, 18 Mar 2026 16:05:25 +0400
Subject: [PATCH 32/33] [lldb] Do not use mkdir -p in makefile on Windows
(#187244)
`Make` uses systems's `mkdir` on Windows even if Git's mkdir.exe is
present in PATH. Windows's mkdir does not support the parameter `-p` and
creates the directory `-p` instead. Few other tests also use `mkdir -p`
but they are linux, objc or macosx related.
---------
Co-authored-by: Charles Zablit <c_zablit at apple.com>
---
lldb/test/API/lang/cpp/incomplete-types/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/test/API/lang/cpp/incomplete-types/Makefile b/lldb/test/API/lang/cpp/incomplete-types/Makefile
index 0cf3f6a31caa2..4e5a331d35b0f 100644
--- a/lldb/test/API/lang/cpp/incomplete-types/Makefile
+++ b/lldb/test/API/lang/cpp/incomplete-types/Makefile
@@ -15,7 +15,7 @@ main.o: NO_LIMIT_DEBUG_INFO_FLAGS = ""
main.o: CFLAGS_EXTRAS = -flimit-debug-info
limit: a.o main.o
- mkdir -p build_limit
+ $(call MKDIR_P,build_limit)
"$(MAKE)" -C $(BUILDDIR)/build_limit -f $(MAKEFILE_RULES) \
EXE=../limit CXX_SOURCES="length.cpp ../a.o ../main.o" \
CFLAGS_EXTRAS=-flimit-debug-info NO_LIMIT_DEBUG_INFO_FLAGS=""
>From 6d4e2e2e0bb90300947bdb9ae7b55f0e629dc464 Mon Sep 17 00:00:00 2001
From: Gonzalo Brito Gadeschi <gonzalob at nvidia.com>
Date: Wed, 18 Mar 2026 06:12:16 -0700
Subject: [PATCH 33/33] fixup
---
clang/include/clang/Basic/Builtins.td | 24 ++++++++++++++++++++
clang/test/Sema/scoped-atomic-ops.c | 32 +++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 599a3f9dfee1c..ea4b0cee32213 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2308,6 +2308,30 @@ def ScopedAtomicFetchMax : AtomicBuiltin {
let Prototype = "void(...)";
}
+def ScopedAtomicFetchFMinimum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fminimum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFetchFMaximum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fmaximum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFetchFMinimumNum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fminimum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFetchFMaximumNum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fmaximum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def ScopedAtomicAddFetch : AtomicBuiltin {
let Spellings = ["__scoped_atomic_add_fetch"];
let Attributes = [CustomTypeChecking];
diff --git a/clang/test/Sema/scoped-atomic-ops.c b/clang/test/Sema/scoped-atomic-ops.c
index 49ddc64ce23eb..71e95df6e732b 100644
--- a/clang/test/Sema/scoped-atomic-ops.c
+++ b/clang/test/Sema/scoped-atomic-ops.c
@@ -93,6 +93,38 @@ void fi3e(float *a, float *b, float *c, float *d, float *e, float *f) {
*e = __scoped_atomic_fetch_udec(e, 1u, __ATOMIC_RELAXED, 42); // expected-error {{address argument to atomic operation must be a pointer to integer ('float *' invalid)}}
}
+void fi3f(float *a, float *b, float *c, float *d, double *e, double *f, double *g, double *h) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *b = __scoped_atomic_fetch_fmaximum(b, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *e = __scoped_atomic_fetch_fminimum(e, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *f = __scoped_atomic_fetch_fmaximum(f, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *g = __scoped_atomic_fetch_fminimum_num(g, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *h = __scoped_atomic_fetch_fmaximum_num(h, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+}
+
+void fi3g(float *a, float *b, float *c, float *d) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+ *b = __scoped_atomic_fetch_fmaximum(b, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+}
+
+void fi3h(float *a, float *b, float *c, float *d) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+ *b = __scoped_atomic_fetch_fmaximum(b, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+}
+
+void fi3i(int *a, int *b, int *c, int *d) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+ *b = __scoped_atomic_fetch_fmaximum(b, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+}
+
int fi4a(int *i) {
int cmp = 0;
int desired = 1;
More information about the llvm-commits
mailing list