[llvm] [LangRef] Make volatile loads non-willreturn (PR #192992)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 21 04:13:52 PDT 2026
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/192992
>From c6e403fc0f349d29b35747f40899c22bd41fc5bc Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 20 Apr 2026 15:18:57 +0200
Subject: [PATCH 1/3] [LangRef] Make volatile loads non-willreturn
We currently define the volatile stores are not willreturn (i.e.
they may trap). However, volatile loads are willreturn.
I think that we should align these semantics to say that volatile
operations are always non-willreturn. There's two motivations for
this:
* In recent versions of the C standard (the current C2y drafts
at least), it is no longer legal to move undefined behavior
across a volatile operation, so I believe this change is
necessary for standards conformance.
* This gives a well-defined (if not very ergonomic) way to
interact with potentially unmapped memory.
---
llvm/docs/LangRef.rst | 11 ++------
llvm/lib/IR/Instruction.cpp | 6 ++--
llvm/test/Transforms/Attributor/nonnull.ll | 4 +--
...r_cached_analysis_for_deleted_functions.ll | 2 +-
.../Transforms/FunctionAttrs/initializes.ll | 10 +++----
.../Transforms/FunctionAttrs/nofpclass.ll | 4 +--
llvm/test/Transforms/FunctionAttrs/nonnull.ll | 8 +++---
llvm/test/Transforms/FunctionAttrs/nosync.ll | 8 +++---
.../Transforms/FunctionAttrs/readattrs.ll | 2 +-
llvm/test/Transforms/GVN/PRE/pre-load-dbg.ll | 24 ++++++++++++----
llvm/test/Transforms/GVN/PRE/volatile.ll | 4 +--
llvm/test/Transforms/LICM/hoist-nounwind.ll | 4 +--
.../LICM/sink-debuginfo-preserve.ll | 16 +++++------
.../LoopFlatten/loop-flatten-gep.ll | 2 +-
.../Transforms/LoopUnroll/unroll-loads-cse.ll | 7 +++--
.../SimplifyCFG/trapping-load-unreachable.ll | 28 +++++++++++++------
16 files changed, 79 insertions(+), 61 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index c73d03dcb6ad9..b269630ae6b97 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -3854,15 +3854,8 @@ volatile operation may not be changed. Different address spaces may
have different trapping behavior when dereferencing an invalid
pointer.
-The compiler may assume execution will continue after a volatile operation,
-so operations which modify memory or may have undefined behavior can be
-hoisted past a volatile operation.
-
-As an exception to the preceding rule, the compiler may not assume execution
-will continue after a volatile store operation. This restriction is necessary
-to support the somewhat common pattern in C of intentionally storing to an
-invalid pointer to crash the program. In the future, it might make sense to
-allow frontends to control this behavior.
+Volatile operations are permitted to trap. The compiler may not assume
+that execution will continue after a volatile operation.
IR-level volatile loads and stores cannot safely be optimized into ``llvm.memcpy``
or ``llvm.memmove`` intrinsics even when those intrinsics are flagged volatile.
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 7db36ed5f8bbb..1932ff72b0a35 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -1256,9 +1256,9 @@ bool Instruction::isSafeToRemove() const {
}
bool Instruction::willReturn() const {
- // Volatile store isn't guaranteed to return; see LangRef.
- if (auto *SI = dyn_cast<StoreInst>(this))
- return !SI->isVolatile();
+ // Volatile operations are not guaranteed to return.
+ if (isVolatile())
+ return false;
if (const auto *CB = dyn_cast<CallBase>(this))
return CB->hasFnAttr(Attribute::WillReturn);
diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll
index eb3cfa1526574..93690ddef6634 100644
--- a/llvm/test/Transforms/Attributor/nonnull.ll
+++ b/llvm/test/Transforms/Attributor/nonnull.ll
@@ -839,11 +839,11 @@ f:
}
; The callsite must execute in order for the attribute to transfer to the parent.
-; The volatile load can't trap, so we can guarantee that we'll get to the call.
+; The volatile load can trap, so we can't guarantee that we'll get to the call.
define i8 @parent6(ptr %a, ptr %b) {
; CHECK-LABEL: define {{[^@]+}}@parent6
-; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr nofree noundef [[B:%.*]]) {
+; CHECK-SAME: (ptr [[A:%.*]], ptr nofree noundef [[B:%.*]]) {
; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[B]], align 1
; CHECK-NEXT: call void @use1nonnull(ptr nonnull [[A]])
; CHECK-NEXT: ret i8 [[C]]
diff --git a/llvm/test/Transforms/Attributor/reduced/clear_cached_analysis_for_deleted_functions.ll b/llvm/test/Transforms/Attributor/reduced/clear_cached_analysis_for_deleted_functions.ll
index 03149f2652a6e..b6cf640eb5519 100644
--- a/llvm/test/Transforms/Attributor/reduced/clear_cached_analysis_for_deleted_functions.ll
+++ b/llvm/test/Transforms/Attributor/reduced/clear_cached_analysis_for_deleted_functions.ll
@@ -12,7 +12,7 @@ target triple = "x86_64-unknown-linux-gnu"
define i32 @clause_LiteralComputeWeight(ptr %call23) {
; CGSCC: Function Attrs: nofree noreturn nounwind
; CGSCC-LABEL: define {{[^@]+}}@clause_LiteralComputeWeight
-; CGSCC-SAME: (ptr nofree nonnull readonly align 8 captures(none) dereferenceable(8) [[CALL23:%.*]]) #[[ATTR0:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree readonly captures(none) [[CALL23:%.*]]) #[[ATTR0:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[DO_BODY:%.*]]
; CGSCC: do.body:
diff --git a/llvm/test/Transforms/FunctionAttrs/initializes.ll b/llvm/test/Transforms/FunctionAttrs/initializes.ll
index 193d0fd589884..067703cced18c 100644
--- a/llvm/test/Transforms/FunctionAttrs/initializes.ll
+++ b/llvm/test/Transforms/FunctionAttrs/initializes.ll
@@ -443,7 +443,7 @@ define void @memset_neg(ptr %p) {
}
define void @memset_volatile(ptr %p) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: write, inaccessiblemem: readwrite)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: write, inaccessiblemem: readwrite)
; CHECK-LABEL: define void @memset_volatile(
; CHECK-SAME: ptr writeonly [[P:%.*]]) #[[ATTR5:[0-9]+]] {
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 2, i64 9, i1 true)
@@ -478,9 +478,9 @@ define void @memcpy(ptr %p, ptr %p2) {
}
define void @memcpy_volatile(ptr %p, ptr %p2) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)
; CHECK-LABEL: define void @memcpy_volatile(
-; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR6:[0-9]+]] {
+; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 9, i1 true)
; CHECK-NEXT: ret void
;
@@ -541,9 +541,9 @@ define void @memmove(ptr %p, ptr %p2) {
}
define void @memmove_volatile(ptr %p, ptr %p2) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)
; CHECK-LABEL: define void @memmove_volatile(
-; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR6]] {
+; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 9, i1 true)
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/FunctionAttrs/nofpclass.ll b/llvm/test/Transforms/FunctionAttrs/nofpclass.ll
index 3ee0498f64815..9ee58df18c598 100644
--- a/llvm/test/Transforms/FunctionAttrs/nofpclass.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nofpclass.ll
@@ -308,8 +308,8 @@ define float @caller_transitive_nonan(float %arg, ptr %ptr) {
ret float %ret
}
;.
-; CHECK: attributes #[[ATTR0]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
-; CHECK: attributes #[[ATTR1]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
+; CHECK: attributes #[[ATTR0]] = { nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) }
+; CHECK: attributes #[[ATTR1]] = { nofree nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) }
; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
;.
diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
index 6611c96362d24..9441db4b80c81 100644
--- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
@@ -852,19 +852,19 @@ f:
}
; The callsite must execute in order for the attribute to transfer to the parent.
-; The volatile load can't trap, so we can guarantee that we'll get to the call.
+; The volatile load can trap, so we can't guarantee that we'll get to the call.
define i8 @parent6(ptr %a, ptr %b) {
; FNATTRS-LABEL: define i8 @parent6(
-; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr [[B:%.*]]) {
+; FNATTRS-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
; FNATTRS-NEXT: [[C:%.*]] = load volatile i8, ptr [[B]], align 1
; FNATTRS-NEXT: call void @use1nonnull(ptr [[A]])
; FNATTRS-NEXT: ret i8 [[C]]
;
; ATTRIBUTOR-LABEL: define i8 @parent6(
-; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr nofree [[B:%.*]]) {
+; ATTRIBUTOR-SAME: ptr [[A:%.*]], ptr nofree [[B:%.*]]) {
; ATTRIBUTOR-NEXT: [[C:%.*]] = load volatile i8, ptr [[B]], align 1
-; ATTRIBUTOR-NEXT: call void @use1nonnull(ptr nonnull [[A]])
+; ATTRIBUTOR-NEXT: call void @use1nonnull(ptr [[A]])
; ATTRIBUTOR-NEXT: ret i8 [[C]]
;
diff --git a/llvm/test/Transforms/FunctionAttrs/nosync.ll b/llvm/test/Transforms/FunctionAttrs/nosync.ll
index 9abfbb21a71a0..9ecbc58732c92 100644
--- a/llvm/test/Transforms/FunctionAttrs/nosync.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nosync.ll
@@ -194,7 +194,7 @@ define void @volatile_store(ptr %0) norecurse nounwind uwtable {
; negative, should not deduce nosync
; volatile load.
define i32 @volatile_load(ptr %0) norecurse nounwind uwtable {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) uwtable
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) uwtable
; CHECK-LABEL: @volatile_load(
; CHECK-NEXT: [[TMP2:%.*]] = load volatile i32, ptr [[TMP0:%.*]], align 4
; CHECK-NEXT: ret i32 [[TMP2]]
@@ -210,7 +210,7 @@ declare void @nosync_function() noinline nounwind uwtable nosync
define void @call_nosync_function() nounwind uwtable noinline {
; CHECK: Function Attrs: noinline nosync nounwind uwtable
; CHECK-LABEL: @call_nosync_function(
-; CHECK-NEXT: tail call void @nosync_function() #[[ATTR11:[0-9]+]]
+; CHECK-NEXT: tail call void @nosync_function() #[[ATTR10:[0-9]+]]
; CHECK-NEXT: ret void
;
tail call void @nosync_function() noinline nounwind uwtable
@@ -224,7 +224,7 @@ declare void @might_sync() noinline nounwind uwtable
define void @call_might_sync() nounwind uwtable noinline {
; CHECK: Function Attrs: noinline nounwind uwtable
; CHECK-LABEL: @call_might_sync(
-; CHECK-NEXT: tail call void @might_sync() #[[ATTR11]]
+; CHECK-NEXT: tail call void @might_sync() #[[ATTR10]]
; CHECK-NEXT: ret void
;
tail call void @might_sync() noinline nounwind uwtable
@@ -236,7 +236,7 @@ declare void @llvm.memset(ptr %dest, i8 %val, i32 %len, i1 %isvolatile)
; negative, checking volatile intrinsics.
define i32 @memcpy_volatile(ptr %ptr1, ptr %ptr2) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)
; CHECK-LABEL: @memcpy_volatile(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[PTR1:%.*]], ptr [[PTR2:%.*]], i32 8, i1 true)
; CHECK-NEXT: ret i32 4
diff --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index ce56e436ce075..bbfe2cd5d74e3 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -346,7 +346,7 @@ define <4 x i32> @test12_2(<4 x ptr> %ptrs) {
}
define i32 @volatile_load(ptr %p) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
+; FNATTRS: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)
; FNATTRS-LABEL: define {{[^@]+}}@volatile_load
; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR11:[0-9]+]] {
; FNATTRS-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4
diff --git a/llvm/test/Transforms/GVN/PRE/pre-load-dbg.ll b/llvm/test/Transforms/GVN/PRE/pre-load-dbg.ll
index f961f23d6b10e..b6261605b708e 100644
--- a/llvm/test/Transforms/GVN/PRE/pre-load-dbg.ll
+++ b/llvm/test/Transforms/GVN/PRE/pre-load-dbg.ll
@@ -16,9 +16,11 @@ define void @withdbg() {
; MDEP-LABEL: define void @withdbg() {
; MDEP-NEXT: [[ENTRY:.*:]]
; MDEP-NEXT: [[AGG_TMP_ENSURED_SROA_0_I:%.*]] = alloca i16, align 1
+; MDEP-NEXT: br i1 true, label %[[ENTRY_LOR_END_CRIT_EDGE:.*]], label %[[LOR_RHS:.*]]
+; MDEP: [[ENTRY_LOR_END_CRIT_EDGE]]:
; MDEP-NEXT: [[TMP11_PRE:%.*]] = load i16, ptr @f, align 1
; MDEP-NEXT: [[TMP12_PRE:%.*]] = load ptr, ptr @m, align 1
-; MDEP-NEXT: br i1 true, label %[[LOR_END:.*]], label %[[LOR_RHS:.*]]
+; MDEP-NEXT: br label %[[LOR_END:.*]]
; MDEP: [[LOR_RHS]]:
; MDEP-NEXT: #dbg_declare(ptr undef, [[META4:![0-9]+]], !DIExpression(), [[META14:![0-9]+]])
; MDEP-NEXT: #dbg_declare(ptr undef, [[META10:![0-9]+]], !DIExpression(), [[META14]])
@@ -43,10 +45,14 @@ define void @withdbg() {
; MDEP-NEXT: store i16 [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_7_I]], ptr [[AGG_TMP_ENSURED_SROA_0_I]], align 1
; MDEP-NEXT: [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_8_I:%.*]] = load volatile i16, ptr @h, align 1
; MDEP-NEXT: store i16 [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_8_I]], ptr [[AGG_TMP_ENSURED_SROA_0_I]], align 1
+; MDEP-NEXT: [[FVALUE:%.*]] = load i16, ptr @f, align 1
+; MDEP-NEXT: [[MVALUE:%.*]] = load ptr, ptr @m, align 1
; MDEP-NEXT: br label %[[LOR_END]]
; MDEP: [[LOR_END]]:
-; MDEP-NEXT: [[CONV_I_I6:%.*]] = sext i16 [[TMP11_PRE]] to i32
-; MDEP-NEXT: store i32 [[CONV_I_I6]], ptr [[TMP12_PRE]], align 1
+; MDEP-NEXT: [[TMP12:%.*]] = phi ptr [ [[TMP12_PRE]], %[[ENTRY_LOR_END_CRIT_EDGE]] ], [ poison, %[[LOR_RHS]] ]
+; MDEP-NEXT: [[TMP11:%.*]] = phi i16 [ [[TMP11_PRE]], %[[ENTRY_LOR_END_CRIT_EDGE]] ], [ poison, %[[LOR_RHS]] ]
+; MDEP-NEXT: [[CONV_I_I6:%.*]] = sext i16 [[TMP11]] to i32
+; MDEP-NEXT: store i32 [[CONV_I_I6]], ptr [[TMP12]], align 1
; MDEP-NEXT: ret void
;
; MSSA-LABEL: define void @withdbg() {
@@ -133,9 +139,11 @@ define void @lessdbg() {
; MDEP-LABEL: define void @lessdbg() {
; MDEP-NEXT: [[ENTRY:.*:]]
; MDEP-NEXT: [[AGG_TMP_ENSURED_SROA_0_I:%.*]] = alloca i16, align 1
+; MDEP-NEXT: br i1 true, label %[[ENTRY_LOR_END_CRIT_EDGE:.*]], label %[[LOR_RHS:.*]]
+; MDEP: [[ENTRY_LOR_END_CRIT_EDGE]]:
; MDEP-NEXT: [[TMP11_PRE:%.*]] = load i16, ptr @f, align 1
; MDEP-NEXT: [[TMP12_PRE:%.*]] = load ptr, ptr @m, align 1
-; MDEP-NEXT: br i1 true, label %[[LOR_END:.*]], label %[[LOR_RHS:.*]]
+; MDEP-NEXT: br label %[[LOR_END:.*]]
; MDEP: [[LOR_RHS]]:
; MDEP-NEXT: [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_I:%.*]] = load volatile i16, ptr @h, align 1
; MDEP-NEXT: store i16 [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_I]], ptr [[AGG_TMP_ENSURED_SROA_0_I]], align 1
@@ -155,10 +163,14 @@ define void @lessdbg() {
; MDEP-NEXT: store i16 [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_7_I]], ptr [[AGG_TMP_ENSURED_SROA_0_I]], align 1
; MDEP-NEXT: [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_8_I:%.*]] = load volatile i16, ptr @h, align 1
; MDEP-NEXT: store i16 [[AGG_TMP_ENSURED_SROA_0_0_COPYLOAD_8_I]], ptr [[AGG_TMP_ENSURED_SROA_0_I]], align 1
+; MDEP-NEXT: [[FVALUE:%.*]] = load i16, ptr @f, align 1
+; MDEP-NEXT: [[MVALUE:%.*]] = load ptr, ptr @m, align 1
; MDEP-NEXT: br label %[[LOR_END]]
; MDEP: [[LOR_END]]:
-; MDEP-NEXT: [[CONV_I_I6:%.*]] = sext i16 [[TMP11_PRE]] to i32
-; MDEP-NEXT: store i32 [[CONV_I_I6]], ptr [[TMP12_PRE]], align 1
+; MDEP-NEXT: [[TMP12:%.*]] = phi ptr [ [[TMP12_PRE]], %[[ENTRY_LOR_END_CRIT_EDGE]] ], [ poison, %[[LOR_RHS]] ]
+; MDEP-NEXT: [[TMP11:%.*]] = phi i16 [ [[TMP11_PRE]], %[[ENTRY_LOR_END_CRIT_EDGE]] ], [ poison, %[[LOR_RHS]] ]
+; MDEP-NEXT: [[CONV_I_I6:%.*]] = sext i16 [[TMP11]] to i32
+; MDEP-NEXT: store i32 [[CONV_I_I6]], ptr [[TMP12]], align 1
; MDEP-NEXT: ret void
;
; MSSA-LABEL: define void @lessdbg() {
diff --git a/llvm/test/Transforms/GVN/PRE/volatile.ll b/llvm/test/Transforms/GVN/PRE/volatile.ll
index 532019119fdb7..38ba5e2cfeb19 100644
--- a/llvm/test/Transforms/GVN/PRE/volatile.ll
+++ b/llvm/test/Transforms/GVN/PRE/volatile.ll
@@ -119,7 +119,7 @@ exit:
}
; Does cross block PRE work with volatiles?
-define i32 @test7(i1 %c, ptr noalias nocapture %p, ptr noalias nocapture %q) {
+define i32 @test7(i1 %c, ptr noalias nocapture align 4 dereferenceable(4) %p, ptr noalias nocapture %q) {
; CHECK-LABEL: @test7(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y_PRE:%.*]] = load i32, ptr [[P:%.*]], align 4
@@ -153,7 +153,7 @@ exit:
; Another volatile PRE case - two paths through a loop
; load in preheader, one path read only, one not
-define i32 @test8(i1 %b, i1 %c, ptr noalias %p, ptr noalias %q) {
+define i32 @test8(i1 %b, i1 %c, ptr noalias align 4 dereferenceable(4) %p, ptr noalias %q) {
; CHECK-LABEL: @test8(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[P:%.*]], align 4
diff --git a/llvm/test/Transforms/LICM/hoist-nounwind.ll b/llvm/test/Transforms/LICM/hoist-nounwind.ll
index 5d27db3bae3e3..3497743f4b3c1 100644
--- a/llvm/test/Transforms/LICM/hoist-nounwind.ll
+++ b/llvm/test/Transforms/LICM/hoist-nounwind.ll
@@ -81,17 +81,17 @@ for.cond.cleanup:
ret i32 0
}
-; Hoist a non-volatile load past volatile load.
+; Do not hoist a non-volatile load past volatile load, because it may trap.
define i32 @test3(ptr noalias nocapture readonly %a, ptr %v) nounwind uwtable {
; CHECK-LABEL: define i32 @test3(
; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]], ptr [[V:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
; CHECK: [[FOR_BODY]]:
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[INC:%.*]], %[[FOR_BODY]] ]
; CHECK-NEXT: [[X_05:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[FOR_BODY]] ]
; CHECK-NEXT: [[XXX:%.*]] = load volatile i32, ptr [[V]], align 4
+; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[X_05]]
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
diff --git a/llvm/test/Transforms/LICM/sink-debuginfo-preserve.ll b/llvm/test/Transforms/LICM/sink-debuginfo-preserve.ll
index de06a86224cf3..91e4f8f1b9150 100644
--- a/llvm/test/Transforms/LICM/sink-debuginfo-preserve.ll
+++ b/llvm/test/Transforms/LICM/sink-debuginfo-preserve.ll
@@ -30,7 +30,7 @@ target triple = "x86_64-apple-macosx10.15.0"
define i32 @main() local_unnamed_addr !dbg !22 {
bb:
- %i = load volatile i32, ptr @b, align 4, !dbg !37, !tbaa !40
+ %i = load i32, ptr @b, align 4, !dbg !37, !tbaa !40
%i1 = icmp sgt i32 %i, -9, !dbg !44
br i1 %i1, label %bb2, label %bb4, !dbg !45
@@ -41,7 +41,7 @@ bb3: ; preds = %bb8
br label %bb4, !dbg !45
bb4: ; preds = %bb3, %bb
- %i5 = load volatile i32, ptr @c, align 4, !dbg !46, !tbaa !40
+ %i5 = load i32, ptr @c, align 4, !dbg !46, !tbaa !40
%i6 = icmp slt i32 %i5, 6, !dbg !47
br i1 %i6, label %bb7, label %bb23, !dbg !48
@@ -49,16 +49,16 @@ bb7: ; preds = %bb4
br label %bb13, !dbg !48
bb8: ; preds = %bb8, %bb2
- %i9 = load volatile i32, ptr @b, align 4, !dbg !49, !tbaa !40
+ %i9 = load i32, ptr @b, align 4, !dbg !49, !tbaa !40
%i10 = add nsw i32 %i9, -1, !dbg !49
- store volatile i32 %i10, ptr @b, align 4, !dbg !49, !tbaa !40
- %i11 = load volatile i32, ptr @b, align 4, !dbg !37, !tbaa !40
+ store i32 %i10, ptr @b, align 4, !dbg !49, !tbaa !40
+ %i11 = load i32, ptr @b, align 4, !dbg !37, !tbaa !40
%i12 = icmp sgt i32 %i11, -9, !dbg !44
br i1 %i12, label %bb8, label %bb3, !dbg !45, !llvm.loop !50
bb13: ; preds = %bb17, %bb7
store i32 0, ptr getelementptr inbounds ([2 x i32], ptr @g_390, i64 0, i64 1), align 4, !dbg !53, !tbaa !40
- %i14 = load volatile i32, ptr @b, align 4, !dbg !54, !tbaa !40
+ %i14 = load i32, ptr @b, align 4, !dbg !54, !tbaa !40
%i15 = icmp eq i32 %i14, 0, !dbg !54
br i1 %i15, label %bb16, label %bb17, !dbg !55
@@ -67,8 +67,8 @@ bb16: ; preds = %bb13
br label %bb17
bb17: ; preds = %bb16, %bb13
- %i18 = load volatile i32, ptr @c, align 4, !dbg !57, !tbaa !40
- %i20 = load volatile i32, ptr @c, align 4, !dbg !46, !tbaa !40
+ %i18 = load i32, ptr @c, align 4, !dbg !57, !tbaa !40
+ %i20 = load i32, ptr @c, align 4, !dbg !46, !tbaa !40
%i21 = icmp slt i32 %i20, 6, !dbg !47
br i1 %i21, label %bb13, label %bb22, !dbg !48, !llvm.loop !58
diff --git a/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll b/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll
index e30001670b1e9..cb91105290d19 100644
--- a/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll
+++ b/llvm/test/Transforms/LoopFlatten/loop-flatten-gep.ll
@@ -72,7 +72,7 @@ for.inner.preheader:
; CHECK: br label %for.outer
for.inner:
%j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]
- %ptr = load volatile ptr, ptr %A, align 4
+ %ptr = load ptr, ptr %A, align 4
%mul = mul i32 %i, %N
%gep = getelementptr inbounds i32, ptr %ptr, i32 %mul
%arrayidx = getelementptr inbounds i32, ptr %gep, i32 %j
diff --git a/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll b/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll
index 77dd3429b684e..4ae1518cf594d 100644
--- a/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll
+++ b/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll
@@ -167,12 +167,13 @@ define void @cse_volatile_loads(ptr %src, ptr noalias %dst, i64 %N) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SRC_4:%.*]] = getelementptr i8, ptr [[SRC]], i64 4
; CHECK-NEXT: [[SRC_12:%.*]] = getelementptr i8, ptr [[SRC]], i64 12
-; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1
-; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[N]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = freeze i64 [[N]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[TMP2]], -1
+; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[TMP2]], 1
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 1
; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_EPIL_PREHEADER:%.*]], label [[ENTRY_NEW:%.*]]
; CHECK: entry.new:
-; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i64 [[N]], [[XTRAITER]]
+; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i64 [[TMP2]], [[XTRAITER]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[IV_NEXT_1:%.*]], [[LOOP]] ]
diff --git a/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll b/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
index 0dc61c64dfa43..04fe15fcad156 100644
--- a/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
+++ b/llvm/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
@@ -10,8 +10,11 @@ define void @test1(i32 %x) nounwind {
; CHECK-LABEL: @test1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[TMP0]], true
-; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: br i1 [[TMP0]], label [[BB:%.*]], label [[RETURN:%.*]]
+; CHECK: bb:
+; CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, ptr null, align 4
+; CHECK-NEXT: unreachable
+; CHECK: return:
; CHECK-NEXT: ret void
;
entry:
@@ -31,8 +34,11 @@ define void @test1_no_null_opt(i32 %x) nounwind #0 {
; CHECK-LABEL: @test1_no_null_opt(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[TMP0]], true
-; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: br i1 [[TMP0]], label [[BB:%.*]], label [[RETURN:%.*]]
+; CHECK: bb:
+; CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, ptr null, align 4
+; CHECK-NEXT: unreachable
+; CHECK: return:
; CHECK-NEXT: ret void
;
entry:
@@ -120,8 +126,11 @@ F:
define void @test5(i1 %C, ptr %P) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true
-; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
+; CHECK-NEXT: br i1 [[C:%.*]], label [[T:%.*]], label [[F:%.*]]
+; CHECK: T:
+; CHECK-NEXT: [[TMP0:%.*]] = cmpxchg volatile ptr [[P:%.*]], i32 0, i32 1 seq_cst seq_cst, align 4
+; CHECK-NEXT: unreachable
+; CHECK: F:
; CHECK-NEXT: ret void
;
entry:
@@ -137,8 +146,11 @@ F:
define void @test6(i1 %C, ptr %P) {
; CHECK-LABEL: @test6(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true
-; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
+; CHECK-NEXT: br i1 [[C:%.*]], label [[T:%.*]], label [[F:%.*]]
+; CHECK: T:
+; CHECK-NEXT: [[TMP0:%.*]] = atomicrmw volatile xchg ptr [[P:%.*]], i32 0 seq_cst, align 4
+; CHECK-NEXT: unreachable
+; CHECK: F:
; CHECK-NEXT: ret void
;
entry:
>From 60bda4f22b226f5b07b1aa7d591494583652ed59 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 21 Apr 2026 13:08:51 +0200
Subject: [PATCH 2/3] Check for volatile in willreturn attributor
---
.../Transforms/IPO/AttributorAttributes.cpp | 11 ++
.../ArgumentPromotion/X86/attributes.ll | 2 +-
.../X86/min-legal-vector-width.ll | 2 +-
.../Attributor/ArgumentPromotion/chained.ll | 2 +-
.../Attributor/ArgumentPromotion/musttail.ll | 2 +-
.../Attributor/ArgumentPromotion/sret.ll | 2 +-
.../IPConstantProp/return-argument.ll | 2 +-
llvm/test/Transforms/Attributor/align.ll | 2 +-
.../Attributor/call-simplify-pointer-info.ll | 7 +-
.../Attributor/dereferenceable-1.ll | 1 -
.../dereferenceable-2-inseltpoison.ll | 4 +-
.../Attributor/dereferenceable-2.ll | 4 +-
llvm/test/Transforms/Attributor/liveness.ll | 8 +-
.../test/Transforms/Attributor/nocapture-1.ll | 124 ++++++------
llvm/test/Transforms/Attributor/nosync.ll | 109 +++++-----
llvm/test/Transforms/Attributor/readattrs.ll | 8 +-
.../Attributor/undefined_behavior.ll | 186 ++++++++++--------
.../Attributor/value-simplify-local-remote.ll | 6 +-
.../Attributor/value-simplify-reachability.ll | 2 +-
.../Transforms/Attributor/value-simplify.ll | 2 +-
.../Transforms/FunctionAttrs/nocapture.ll | 60 +++---
.../Transforms/FunctionAttrs/readattrs.ll | 4 +-
.../Transforms/FunctionAttrs/writeonly.ll | 24 +--
23 files changed, 308 insertions(+), 266 deletions(-)
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 09276c3667cb9..dbc19d5e9c1a3 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -3349,6 +3349,17 @@ struct AAWillReturnImpl : public AAWillReturn {
UsedAssumedInformation))
return indicatePessimisticFixpoint();
+ auto CheckForVolatile = [&](Instruction &I) {
+ // Volatile operations are not willreturn.
+ return !I.isVolatile();
+ };
+ if (!A.checkForAllInstructions(CheckForVolatile, *this,
+ {Instruction::Load, Instruction::Store,
+ Instruction::AtomicCmpXchg,
+ Instruction::AtomicRMW},
+ UsedAssumedInformation))
+ return indicatePessimisticFixpoint();
+
return ChangeStatus::UNCHANGED;
}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
index 89def2bedea11..2a45b2e8ea3e1 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
@@ -145,7 +145,7 @@ attributes #2 = { argmemonly nounwind }
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable }
; TUNIT: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR3]] = { nofree willreturn memory(write) }
-; TUNIT: attributes #[[ATTR4]] = { nofree nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind willreturn }
;.
; CGSCC: [[META0]] = !{}
;.
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
index fffe50fde1e50..6bc46e49573ef 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
@@ -554,7 +554,7 @@ attributes #5 = { argmemonly nounwind }
; TUNIT: attributes #[[ATTR3]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="256" "target-features"="+avx2" }
; TUNIT: attributes #[[ATTR4:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR5]] = { nofree willreturn memory(write) }
-; TUNIT: attributes #[[ATTR6]] = { nofree nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR6]] = { nofree norecurse nosync nounwind willreturn }
;.
; CGSCC: [[META0]] = !{}
;.
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll
index bfc616da0b2b1..9ee62f3cfdd02 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll
@@ -46,7 +46,7 @@ entry:
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; TUNIT: attributes #[[ATTR1]] = { nofree nosync nounwind willreturn memory(read) }
+; TUNIT: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind willreturn memory(read) }
;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll
index ce71d0bf0df2a..d3d3d3309abe8 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll
@@ -171,7 +171,7 @@ define i32 @caller2b(ptr %g) {
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; TUNIT: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
-; TUNIT: attributes #[[ATTR4]] = { nofree nosync nounwind willreturn memory(read) }
+; TUNIT: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind willreturn memory(read) }
; TUNIT: attributes #[[ATTR5]] = { nofree nosync nounwind willreturn memory(write) }
; TUNIT: attributes #[[ATTR6]] = { nofree nosync nounwind willreturn }
;.
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll
index 1df0f3c55cc2d..696913fbfb055 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll
@@ -61,7 +61,7 @@ define void @f() {
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; TUNIT: attributes #[[ATTR2]] = { nofree nosync nounwind willreturn memory(write) }
+; TUNIT: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind willreturn memory(write) }
;.
; CGSCC: [[META0]] = !{}
;.
diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
index 15a1ed0e62763..893d14743a70a 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
@@ -120,7 +120,7 @@ declare i32 @__gxx_personality_v0(...)
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; TUNIT: attributes #[[ATTR2]] = { nofree nosync nounwind willreturn memory(write) }
+; TUNIT: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind willreturn memory(write) }
;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll
index 90515dcbb3685..586aecb7cae1f 100644
--- a/llvm/test/Transforms/Attributor/align.ll
+++ b/llvm/test/Transforms/Attributor/align.ll
@@ -1233,7 +1233,7 @@ attributes #2 = { null_pointer_is_valid }
; TUNIT: attributes #[[ATTR12]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind }
; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind willreturn memory(read) }
-; TUNIT: attributes #[[ATTR15]] = { nofree nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind willreturn }
;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable }
diff --git a/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll
index f8d48f29cd0ba..aea1238ef04e0 100644
--- a/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll
+++ b/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll
@@ -204,7 +204,7 @@ define i8 @call_partially_simplifiable_1() {
; TUNIT-NEXT: [[I3:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 3
; TUNIT-NEXT: store i8 3, ptr [[I3]], align 1
; TUNIT-NEXT: [[I4:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 4
-; TUNIT-NEXT: [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree noundef nonnull readonly align 2 captures(none) dereferenceable(1022) [[I2]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(1021) [[I3]]) #[[ATTR3:[0-9]+]]
+; TUNIT-NEXT: [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree noundef nonnull readonly align 2 captures(none) dereferenceable(1022) [[I2]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(1021) [[I3]]) #[[ATTR2]]
; TUNIT-NEXT: ret i8 [[R]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
@@ -247,7 +247,7 @@ define i8 @call_partially_simplifiable_2(i1 %cond) {
; TUNIT-NEXT: store i8 3, ptr [[I53]], align 1
; TUNIT-NEXT: [[I54:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 54
; TUNIT-NEXT: [[SEL:%.*]] = select i1 [[COND]], ptr [[I51]], ptr [[I52]]
-; TUNIT-NEXT: [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree nonnull readonly captures(none) dereferenceable(972) [[SEL]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[I53]]) #[[ATTR3]]
+; TUNIT-NEXT: [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree nonnull readonly captures(none) dereferenceable(972) [[SEL]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[I53]]) #[[ATTR2]]
; TUNIT-NEXT: ret i8 [[R]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
@@ -289,8 +289,7 @@ entry:
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
-; TUNIT: attributes #[[ATTR2]] = { nofree nosync nounwind willreturn memory(read) }
-; TUNIT: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind willreturn memory(read) }
+; TUNIT: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind willreturn memory(read) }
;.
; CGSCC: [[META0]] = !{}
;.
diff --git a/llvm/test/Transforms/Attributor/dereferenceable-1.ll b/llvm/test/Transforms/Attributor/dereferenceable-1.ll
index 5bff2a2e6b208..5699284128388 100644
--- a/llvm/test/Transforms/Attributor/dereferenceable-1.ll
+++ b/llvm/test/Transforms/Attributor/dereferenceable-1.ll
@@ -238,7 +238,6 @@ define void @f7_2(i1 %cnd) {
; CHECK-SAME: (i1 noundef [[CND:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[PTR:%.*]] = tail call nonnull align 4 dereferenceable(4) ptr @unkown_ptr() #[[ATTR1]]
; CHECK-NEXT: [[A:%.*]] = tail call i32 @unkown_f(ptr noundef nonnull align 4 dereferenceable(4) [[PTR]]) #[[ATTR1]]
-; CHECK-NEXT: [[ARG_A_0:%.*]] = load i32, ptr [[PTR]], align 4
; CHECK-NEXT: [[B:%.*]] = tail call i32 @unkown_f(ptr noundef nonnull align 4 dereferenceable(4) [[PTR]]) #[[ATTR1]]
; CHECK-NEXT: br i1 [[CND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
; CHECK: if.true:
diff --git a/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll b/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll
index e5324aaba71ea..55ca98b80ffe2 100644
--- a/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll
+++ b/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll
@@ -211,7 +211,7 @@ exit:
; The 2nd and 3rd loads may never execute.
define void @volatile_is_not_dereferenceable(ptr %ptr) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable
; CHECK-SAME: (ptr nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: [[T0:%.*]] = load volatile i16, ptr [[PTR]], align 2
@@ -565,7 +565,7 @@ end:
; CHECK: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR3]] = { nofree norecurse nounwind memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
;.
; CHECK: [[META0]] = !{}
diff --git a/llvm/test/Transforms/Attributor/dereferenceable-2.ll b/llvm/test/Transforms/Attributor/dereferenceable-2.ll
index d7d33283ba743..a03b93c138bc7 100644
--- a/llvm/test/Transforms/Attributor/dereferenceable-2.ll
+++ b/llvm/test/Transforms/Attributor/dereferenceable-2.ll
@@ -211,7 +211,7 @@ exit:
; The 2nd and 3rd loads may never execute.
define void @volatile_is_not_dereferenceable(ptr %ptr) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable
; CHECK-SAME: (ptr nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: [[T0:%.*]] = load volatile i16, ptr [[PTR]], align 2
@@ -565,7 +565,7 @@ end:
; CHECK: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR3]] = { nofree norecurse nounwind memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
;.
; CHECK: [[META0]] = !{}
diff --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll
index c03d8d560b1f0..84fc43d5ae01c 100644
--- a/llvm/test/Transforms/Attributor/liveness.ll
+++ b/llvm/test/Transforms/Attributor/liveness.ll
@@ -68,13 +68,13 @@ define internal i32 @dead_internal_func(i32 %0) {
}
define i32 @volatile_load(ptr) norecurse nounwind uwtable {
-; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
+; TUNIT: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite) uwtable
; TUNIT-LABEL: define {{[^@]+}}@volatile_load
; TUNIT-SAME: (ptr nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR6:[0-9]+]] {
; TUNIT-NEXT: [[TMP2:%.*]] = load volatile i32, ptr [[TMP0]], align 4
; TUNIT-NEXT: ret i32 [[TMP2]]
;
-; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
+; CGSCC: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite) uwtable
; CGSCC-LABEL: define {{[^@]+}}@volatile_load
; CGSCC-SAME: (ptr nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
; CGSCC-NEXT: [[TMP2:%.*]] = load volatile i32, ptr [[TMP0]], align 4
@@ -2688,7 +2688,7 @@ declare void @llvm.lifetime.end.p0(ptr %1)
; TUNIT: attributes #[[ATTR3]] = { noreturn nounwind }
; TUNIT: attributes #[[ATTR4]] = { noreturn }
; TUNIT: attributes #[[ATTR5]] = { nosync memory(none) }
-; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable }
+; TUNIT: attributes #[[ATTR6]] = { nofree norecurse nounwind memory(argmem: readwrite) uwtable }
; TUNIT: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR8]] = { nofree norecurse noreturn nosync nounwind memory(none) }
; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
@@ -2709,7 +2709,7 @@ declare void @llvm.lifetime.end.p0(ptr %1)
; CGSCC: attributes #[[ATTR4]] = { noreturn }
; CGSCC: attributes #[[ATTR5]] = { nosync memory(none) }
; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable }
+; CGSCC: attributes #[[ATTR7]] = { nofree norecurse nounwind memory(argmem: readwrite) uwtable }
; CGSCC: attributes #[[ATTR8]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable }
; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; CGSCC: attributes #[[ATTR10]] = { nofree norecurse noreturn nosync nounwind memory(none) }
diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll
index 034b5ef397f0a..4094145e1306f 100644
--- a/llvm/test/Transforms/Attributor/nocapture-1.ll
+++ b/llvm/test/Transforms/Attributor/nocapture-1.ll
@@ -35,13 +35,13 @@ define void @c3(ptr %q) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@c3
; TUNIT-SAME: (ptr nofree writeonly [[Q:%.*]]) #[[ATTR1]] {
-; TUNIT-NEXT: call void @c2(ptr nofree writeonly [[Q]]) #[[ATTR17:[0-9]+]]
+; TUNIT-NEXT: call void @c2(ptr nofree writeonly [[Q]]) #[[ATTR18:[0-9]+]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@c3
; CGSCC-SAME: (ptr nofree writeonly [[Q:%.*]]) #[[ATTR2:[0-9]+]] {
-; CGSCC-NEXT: call void @c2(ptr nofree writeonly [[Q]]) #[[ATTR20:[0-9]+]]
+; CGSCC-NEXT: call void @c2(ptr nofree writeonly [[Q]]) #[[ATTR21:[0-9]+]]
; CGSCC-NEXT: ret void
;
call void @c2(ptr %q)
@@ -187,14 +187,14 @@ define i1 @c7(ptr %q, i32 %bitno) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; TUNIT-LABEL: define {{[^@]+}}@c7
; TUNIT-SAME: (ptr nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR2]] {
-; TUNIT-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR18:[0-9]+]]
+; TUNIT-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR19:[0-9]+]]
; TUNIT-NEXT: [[VAL:%.*]] = load i1, ptr [[PTR]], align 1
; TUNIT-NEXT: ret i1 [[VAL]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)
; CGSCC-LABEL: define {{[^@]+}}@c7
; CGSCC-SAME: (ptr nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR6:[0-9]+]] {
-; CGSCC-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR21:[0-9]+]]
+; CGSCC-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR22:[0-9]+]]
; CGSCC-NEXT: [[VAL:%.*]] = load i1, ptr [[PTR]], align 1
; CGSCC-NEXT: ret i1 [[VAL]]
;
@@ -293,13 +293,13 @@ define void @nc2(ptr %p, ptr %q) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@nc2
; TUNIT-SAME: (ptr nofree captures(none) [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR5]] {
-; TUNIT-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr nofree [[Q]], ptr nofree captures(none) [[P]], i1 noundef false) #[[ATTR19:[0-9]+]]
+; TUNIT-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr nofree [[Q]], ptr nofree captures(none) [[P]], i1 noundef false) #[[ATTR20:[0-9]+]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@nc2
; CGSCC-SAME: (ptr nofree align 4 captures(none) [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR8:[0-9]+]] {
-; CGSCC-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr nofree [[Q]], ptr nofree align 4 captures(none) [[P]], i1 noundef false) #[[ATTR22:[0-9]+]]
+; CGSCC-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr nofree [[Q]], ptr nofree align 4 captures(none) [[P]], i1 noundef false) #[[ATTR23:[0-9]+]]
; CGSCC-NEXT: ret void
;
%1 = call i32 @nc1(ptr %q, ptr %p, i1 0) ; <i32> [#uses=0]
@@ -324,13 +324,13 @@ define void @nc4(ptr %p) {
; TUNIT: Function Attrs: nounwind memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@nc4
; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR6:[0-9]+]] {
-; TUNIT-NEXT: call void @external(ptr nofree readonly [[P]]) #[[ATTR20:[0-9]+]]
+; TUNIT-NEXT: call void @external(ptr nofree readonly [[P]]) #[[ATTR21:[0-9]+]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nounwind memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@nc4
; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR9:[0-9]+]] {
-; CGSCC-NEXT: call void @external(ptr nofree readonly [[P]]) #[[ATTR23:[0-9]+]]
+; CGSCC-NEXT: call void @external(ptr nofree readonly [[P]]) #[[ATTR24:[0-9]+]]
; CGSCC-NEXT: ret void
;
call void @external(ptr %p)
@@ -584,17 +584,17 @@ define void @test_atomicrmw(ptr %p) {
}
define void @test_volatile(ptr %x) {
-; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; TUNIT: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@test_volatile
-; TUNIT-SAME: (ptr nofree align 4 [[X:%.*]]) #[[ATTR8]] {
+; TUNIT-SAME: (ptr nofree align 4 [[X:%.*]]) #[[ATTR9:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[X]], i64 1
; TUNIT-NEXT: store volatile i32 0, ptr [[GEP]], align 4
; TUNIT-NEXT: ret void
;
-; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; CGSCC: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@test_volatile
-; CGSCC-SAME: (ptr nofree align 4 [[X:%.*]]) #[[ATTR11]] {
+; CGSCC-SAME: (ptr nofree align 4 [[X:%.*]]) #[[ATTR12:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[X]], i64 1
; CGSCC-NEXT: store volatile i32 0, ptr [[GEP]], align 4
@@ -609,17 +609,17 @@ entry:
define void @nocaptureLaunder(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@nocaptureLaunder
-; TUNIT-SAME: (ptr nofree captures(none) [[P:%.*]]) #[[ATTR9:[0-9]+]] {
+; TUNIT-SAME: (ptr nofree captures(none) [[P:%.*]]) #[[ATTR10:[0-9]+]] {
; TUNIT-NEXT: entry:
-; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR21:[0-9]+]]
+; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR22:[0-9]+]]
; TUNIT-NEXT: store i8 42, ptr [[B]], align 1
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@nocaptureLaunder
-; CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]]) #[[ATTR12:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree captures(none) [[P:%.*]]) #[[ATTR13:[0-9]+]] {
; CGSCC-NEXT: entry:
-; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR24:[0-9]+]]
+; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR25:[0-9]+]]
; CGSCC-NEXT: store i8 42, ptr [[B]], align 1
; CGSCC-NEXT: ret void
;
@@ -634,14 +634,14 @@ define void @captureLaunder(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@captureLaunder
; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {
-; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR21]]
+; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR22]]
; TUNIT-NEXT: store ptr [[B]], ptr @g2, align 8
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@captureLaunder
; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR7]] {
-; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR24]]
+; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr nofree [[P]]) #[[ATTR25]]
; CGSCC-NEXT: store ptr [[B]], ptr @g2, align 8
; CGSCC-NEXT: ret void
;
@@ -653,17 +653,17 @@ define void @captureLaunder(ptr %p) {
define void @nocaptureStrip(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; TUNIT-LABEL: define {{[^@]+}}@nocaptureStrip
-; TUNIT-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR10:[0-9]+]] {
+; TUNIT-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR11:[0-9]+]] {
; TUNIT-NEXT: entry:
-; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR22:[0-9]+]]
+; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR23:[0-9]+]]
; TUNIT-NEXT: store i8 42, ptr [[B]], align 1
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CGSCC-LABEL: define {{[^@]+}}@nocaptureStrip
-; CGSCC-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR13:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR14:[0-9]+]] {
; CGSCC-NEXT: entry:
-; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR21]]
+; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR22]]
; CGSCC-NEXT: store i8 42, ptr [[B]], align 1
; CGSCC-NEXT: ret void
;
@@ -678,14 +678,14 @@ define void @captureStrip(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@captureStrip
; TUNIT-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR1]] {
-; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR22]]
+; TUNIT-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR23]]
; TUNIT-NEXT: store ptr [[B]], ptr @g3, align 8
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@captureStrip
; CGSCC-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR1]] {
-; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR21]]
+; CGSCC-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr noalias nofree readnone [[P]]) #[[ATTR22]]
; CGSCC-NEXT: store ptr [[B]], ptr @g3, align 8
; CGSCC-NEXT: ret void
;
@@ -752,13 +752,13 @@ define i1 @nocaptureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x)
define i1 @captureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) null_pointer_is_valid {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp
-; TUNIT-SAME: (ptr nofree noundef readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR11:[0-9]+]] {
+; TUNIT-SAME: (ptr nofree noundef readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR12:[0-9]+]] {
; TUNIT-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
; TUNIT-NEXT: ret i1 [[TMP1]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp
-; CGSCC-SAME: (ptr nofree noundef readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR14:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree noundef readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR15:[0-9]+]] {
; CGSCC-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
; CGSCC-NEXT: ret i1 [[TMP1]]
;
@@ -783,14 +783,14 @@ declare ptr @unknownpi8pi8(ptr,ptr returned)
define ptr @test_returned1(ptr %A, ptr returned %B) nounwind readonly {
; TUNIT: Function Attrs: nosync nounwind memory(read)
; TUNIT-LABEL: define {{[^@]+}}@test_returned1
-; TUNIT-SAME: (ptr captures(none) [[A:%.*]], ptr returned [[B:%.*]]) #[[ATTR12:[0-9]+]] {
+; TUNIT-SAME: (ptr captures(none) [[A:%.*]], ptr returned [[B:%.*]]) #[[ATTR13:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[P:%.*]] = call ptr @unknownpi8pi8(ptr [[A]], ptr [[B]])
; TUNIT-NEXT: ret ptr [[P]]
;
; CGSCC: Function Attrs: nosync nounwind memory(read)
; CGSCC-LABEL: define {{[^@]+}}@test_returned1
-; CGSCC-SAME: (ptr captures(none) [[A:%.*]], ptr returned [[B:%.*]]) #[[ATTR15:[0-9]+]] {
+; CGSCC-SAME: (ptr captures(none) [[A:%.*]], ptr returned [[B:%.*]]) #[[ATTR16:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[P:%.*]] = call ptr @unknownpi8pi8(ptr [[A]], ptr [[B]])
; CGSCC-NEXT: ret ptr [[P]]
@@ -803,16 +803,16 @@ entry:
define ptr @test_returned2(ptr %A, ptr %B) {
; TUNIT: Function Attrs: nosync nounwind memory(read)
; TUNIT-LABEL: define {{[^@]+}}@test_returned2
-; TUNIT-SAME: (ptr readonly [[A:%.*]], ptr readonly [[B:%.*]]) #[[ATTR12]] {
+; TUNIT-SAME: (ptr readonly [[A:%.*]], ptr readonly [[B:%.*]]) #[[ATTR13]] {
; TUNIT-NEXT: entry:
-; TUNIT-NEXT: [[P:%.*]] = call ptr @unknownpi8pi8(ptr readonly [[A]], ptr readonly [[B]]) #[[ATTR12]]
+; TUNIT-NEXT: [[P:%.*]] = call ptr @unknownpi8pi8(ptr readonly [[A]], ptr readonly [[B]]) #[[ATTR13]]
; TUNIT-NEXT: ret ptr [[P]]
;
; CGSCC: Function Attrs: nosync nounwind memory(read)
; CGSCC-LABEL: define {{[^@]+}}@test_returned2
-; CGSCC-SAME: (ptr readonly [[A:%.*]], ptr readonly [[B:%.*]]) #[[ATTR15]] {
+; CGSCC-SAME: (ptr readonly [[A:%.*]], ptr readonly [[B:%.*]]) #[[ATTR16]] {
; CGSCC-NEXT: entry:
-; CGSCC-NEXT: [[P:%.*]] = call ptr @unknownpi8pi8(ptr readonly [[A]], ptr readonly [[B]]) #[[ATTR15]]
+; CGSCC-NEXT: [[P:%.*]] = call ptr @unknownpi8pi8(ptr readonly [[A]], ptr readonly [[B]]) #[[ATTR16]]
; CGSCC-NEXT: ret ptr [[P]]
;
entry:
@@ -828,13 +828,13 @@ declare void @val_use(i8 %ptr) readonly nounwind willreturn
define void @ptr_uses(ptr %ptr, ptr %wptr) {
; TUNIT: Function Attrs: mustprogress nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@ptr_uses
-; TUNIT-SAME: (ptr nofree [[PTR:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[WPTR:%.*]]) #[[ATTR14:[0-9]+]] {
+; TUNIT-SAME: (ptr nofree [[PTR:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[WPTR:%.*]]) #[[ATTR15:[0-9]+]] {
; TUNIT-NEXT: store i8 0, ptr [[WPTR]], align 1
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@ptr_uses
-; CGSCC-SAME: (ptr nofree [[PTR:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[WPTR:%.*]]) #[[ATTR17:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree [[PTR:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[WPTR:%.*]]) #[[ATTR18:[0-9]+]] {
; CGSCC-NEXT: store i8 0, ptr [[WPTR]], align 1
; CGSCC-NEXT: ret void
;
@@ -857,20 +857,21 @@ declare ptr @llvm.strip.invariant.group.p0(ptr)
; TUNIT: attributes #[[ATTR6]] = { nounwind memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR7]] = { nofree nosync nounwind memory(write) }
; TUNIT: attributes #[[ATTR8]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
-; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
-; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
-; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
-; TUNIT: attributes #[[ATTR12]] = { nosync nounwind memory(read) }
-; TUNIT: attributes #[[ATTR13:[0-9]+]] = { nounwind willreturn memory(read) }
-; TUNIT: attributes #[[ATTR14]] = { mustprogress nosync nounwind willreturn }
-; TUNIT: attributes #[[ATTR15:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }
-; TUNIT: attributes #[[ATTR16:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
-; TUNIT: attributes #[[ATTR17]] = { nofree nosync nounwind willreturn memory(write) }
-; TUNIT: attributes #[[ATTR18]] = { nofree nosync nounwind willreturn memory(none) }
-; TUNIT: attributes #[[ATTR19]] = { nofree nosync nounwind willreturn }
-; TUNIT: attributes #[[ATTR20]] = { nounwind }
-; TUNIT: attributes #[[ATTR21]] = { nofree willreturn }
-; TUNIT: attributes #[[ATTR22]] = { nofree nosync willreturn }
+; TUNIT: attributes #[[ATTR9]] = { nofree norecurse nounwind memory(argmem: readwrite) }
+; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
+; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
+; TUNIT: attributes #[[ATTR12]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
+; TUNIT: attributes #[[ATTR13]] = { nosync nounwind memory(read) }
+; TUNIT: attributes #[[ATTR14:[0-9]+]] = { nounwind willreturn memory(read) }
+; TUNIT: attributes #[[ATTR15]] = { mustprogress nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR16:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }
+; TUNIT: attributes #[[ATTR17:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+; TUNIT: attributes #[[ATTR18]] = { nofree nosync nounwind willreturn memory(write) }
+; TUNIT: attributes #[[ATTR19]] = { nofree nosync nounwind willreturn memory(none) }
+; TUNIT: attributes #[[ATTR20]] = { nofree nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR21]] = { nounwind }
+; TUNIT: attributes #[[ATTR22]] = { nofree willreturn }
+; TUNIT: attributes #[[ATTR23]] = { nofree nosync willreturn }
;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
@@ -884,17 +885,18 @@ declare ptr @llvm.strip.invariant.group.p0(ptr)
; CGSCC: attributes #[[ATTR9]] = { nounwind memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR10]] = { nofree nosync nounwind memory(write) }
; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
-; CGSCC: attributes #[[ATTR12]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
-; CGSCC: attributes #[[ATTR13]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
-; CGSCC: attributes #[[ATTR14]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
-; CGSCC: attributes #[[ATTR15]] = { nosync nounwind memory(read) }
-; CGSCC: attributes #[[ATTR16:[0-9]+]] = { nounwind willreturn memory(read) }
-; CGSCC: attributes #[[ATTR17]] = { mustprogress nosync nounwind willreturn }
-; CGSCC: attributes #[[ATTR18:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }
-; CGSCC: attributes #[[ATTR19:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
-; CGSCC: attributes #[[ATTR20]] = { nofree nounwind willreturn memory(write) }
-; CGSCC: attributes #[[ATTR21]] = { nofree nosync willreturn }
-; CGSCC: attributes #[[ATTR22]] = { nofree nounwind willreturn }
-; CGSCC: attributes #[[ATTR23]] = { nounwind }
-; CGSCC: attributes #[[ATTR24]] = { nofree willreturn }
+; CGSCC: attributes #[[ATTR12]] = { nofree norecurse nounwind memory(argmem: readwrite) }
+; CGSCC: attributes #[[ATTR13]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) }
+; CGSCC: attributes #[[ATTR14]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
+; CGSCC: attributes #[[ATTR15]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
+; CGSCC: attributes #[[ATTR16]] = { nosync nounwind memory(read) }
+; CGSCC: attributes #[[ATTR17:[0-9]+]] = { nounwind willreturn memory(read) }
+; CGSCC: attributes #[[ATTR18]] = { mustprogress nosync nounwind willreturn }
+; CGSCC: attributes #[[ATTR19:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }
+; CGSCC: attributes #[[ATTR20:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+; CGSCC: attributes #[[ATTR21]] = { nofree nounwind willreturn memory(write) }
+; CGSCC: attributes #[[ATTR22]] = { nofree nosync willreturn }
+; CGSCC: attributes #[[ATTR23]] = { nofree nounwind willreturn }
+; CGSCC: attributes #[[ATTR24]] = { nounwind }
+; CGSCC: attributes #[[ATTR25]] = { nofree willreturn }
;.
diff --git a/llvm/test/Transforms/Attributor/nosync.ll b/llvm/test/Transforms/Attributor/nosync.ll
index c15bd775ddb4d..39e9c055fd3cd 100644
--- a/llvm/test/Transforms/Attributor/nosync.ll
+++ b/llvm/test/Transforms/Attributor/nosync.ll
@@ -103,9 +103,9 @@ define i32 @load_acquire(ptr nocapture readonly %arg) norecurse nounwind uwtable
; }
define void @load_release(ptr nocapture %arg) norecurse nounwind uwtable {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite) uwtable
; CHECK-LABEL: define {{[^@]+}}@load_release
-; CHECK-SAME: (ptr nofree noundef writeonly align 4 captures(none) [[ARG:%.*]]) #[[ATTR2]] {
+; CHECK-SAME: (ptr nofree noundef writeonly align 4 captures(none) [[ARG:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: store atomic volatile i32 10, ptr [[ARG]] release, align 4
; CHECK-NEXT: ret void
;
@@ -116,9 +116,9 @@ define void @load_release(ptr nocapture %arg) norecurse nounwind uwtable {
; TEST 6 - negative volatile, relaxed atomic
define void @load_volatile_release(ptr nocapture %arg) norecurse nounwind uwtable {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite) uwtable
; CHECK-LABEL: define {{[^@]+}}@load_volatile_release
-; CHECK-SAME: (ptr nofree noundef writeonly align 4 captures(none) [[ARG:%.*]]) #[[ATTR2]] {
+; CHECK-SAME: (ptr nofree noundef writeonly align 4 captures(none) [[ARG:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: store atomic volatile i32 10, ptr [[ARG]] release, align 4
; CHECK-NEXT: ret void
;
@@ -133,9 +133,9 @@ define void @load_volatile_release(ptr nocapture %arg) norecurse nounwind uwtabl
; }
define void @volatile_store(ptr %arg) norecurse nounwind uwtable {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite) uwtable
; CHECK-LABEL: define {{[^@]+}}@volatile_store
-; CHECK-SAME: (ptr nofree noundef align 4 [[ARG:%.*]]) #[[ATTR2]] {
+; CHECK-SAME: (ptr nofree noundef align 4 [[ARG:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: store volatile i32 14, ptr [[ARG]], align 4
; CHECK-NEXT: ret void
;
@@ -151,9 +151,9 @@ define void @volatile_store(ptr %arg) norecurse nounwind uwtable {
; }
define i32 @volatile_load(ptr %arg) norecurse nounwind uwtable {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
+; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite) uwtable
; CHECK-LABEL: define {{[^@]+}}@volatile_load
-; CHECK-SAME: (ptr nofree noundef align 4 [[ARG:%.*]]) #[[ATTR2]] {
+; CHECK-SAME: (ptr nofree noundef align 4 [[ARG:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: [[I:%.*]] = load volatile i32, ptr [[ARG]], align 4
; CHECK-NEXT: ret i32 [[I]]
;
@@ -169,8 +169,8 @@ declare void @nosync_function() noinline nounwind uwtable nosync
define void @call_nosync_function() noinline nounwind uwtable {
; CHECK: Function Attrs: noinline nosync nounwind uwtable
; CHECK-LABEL: define {{[^@]+}}@call_nosync_function
-; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
-; CHECK-NEXT: tail call void @nosync_function() #[[ATTR4:[0-9]+]]
+; CHECK-SAME: () #[[ATTR4:[0-9]+]] {
+; CHECK-NEXT: tail call void @nosync_function() #[[ATTR5:[0-9]+]]
; CHECK-NEXT: ret void
;
tail call void @nosync_function() noinline nounwind uwtable
@@ -185,8 +185,8 @@ declare void @might_sync() noinline nounwind uwtable
define void @call_might_sync() noinline nounwind uwtable {
; CHECK: Function Attrs: noinline nounwind uwtable
; CHECK-LABEL: define {{[^@]+}}@call_might_sync
-; CHECK-SAME: () #[[ATTR4]] {
-; CHECK-NEXT: tail call void @might_sync() #[[ATTR4]]
+; CHECK-SAME: () #[[ATTR5]] {
+; CHECK-NEXT: tail call void @might_sync() #[[ATTR5]]
; CHECK-NEXT: ret void
;
tail call void @might_sync() noinline nounwind uwtable
@@ -199,9 +199,9 @@ define void @call_might_sync() noinline nounwind uwtable {
define i32 @scc1(ptr %arg) noinline nounwind uwtable {
; CHECK: Function Attrs: nofree noinline nounwind memory(argmem: readwrite) uwtable
; CHECK-LABEL: define {{[^@]+}}@scc1
-; CHECK-SAME: (ptr nofree [[ARG:%.*]]) #[[ATTR5:[0-9]+]] {
-; CHECK-NEXT: tail call void @scc2(ptr nofree [[ARG]]) #[[ATTR20:[0-9]+]]
-; CHECK-NEXT: [[VAL:%.*]] = tail call i32 @volatile_load(ptr nofree noundef align 4 [[ARG]]) #[[ATTR20]]
+; CHECK-SAME: (ptr nofree [[ARG:%.*]]) #[[ATTR6:[0-9]+]] {
+; CHECK-NEXT: tail call void @scc2(ptr nofree [[ARG]]) #[[ATTR21:[0-9]+]]
+; CHECK-NEXT: [[VAL:%.*]] = tail call i32 @volatile_load(ptr nofree noundef align 4 [[ARG]]) #[[ATTR21]]
; CHECK-NEXT: ret i32 [[VAL]]
;
tail call void @scc2(ptr %arg)
@@ -212,8 +212,8 @@ define i32 @scc1(ptr %arg) noinline nounwind uwtable {
define void @scc2(ptr %arg) noinline nounwind uwtable {
; CHECK: Function Attrs: nofree noinline nounwind memory(argmem: readwrite) uwtable
; CHECK-LABEL: define {{[^@]+}}@scc2
-; CHECK-SAME: (ptr nofree [[ARG:%.*]]) #[[ATTR5]] {
-; CHECK-NEXT: [[I:%.*]] = tail call i32 @scc1(ptr nofree [[ARG]]) #[[ATTR20]]
+; CHECK-SAME: (ptr nofree [[ARG:%.*]]) #[[ATTR6]] {
+; CHECK-NEXT: [[I:%.*]] = tail call i32 @scc1(ptr nofree [[ARG]]) #[[ATTR21]]
; CHECK-NEXT: ret void
;
%i = tail call i32 @scc1(ptr %arg)
@@ -242,7 +242,7 @@ define void @scc2(ptr %arg) noinline nounwind uwtable {
define void @foo1(ptr %arg, ptr %arg1) {
; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn
; CHECK-LABEL: define {{[^@]+}}@foo1
-; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR6:[0-9]+]] {
+; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR7:[0-9]+]] {
; CHECK-NEXT: store i32 100, ptr [[ARG]], align 4
; CHECK-NEXT: fence release
; CHECK-NEXT: store atomic i8 1, ptr [[ARG1]] monotonic, align 1
@@ -257,7 +257,7 @@ define void @foo1(ptr %arg, ptr %arg1) {
define void @bar(ptr %arg, ptr %arg1) {
; CHECK: Function Attrs: nofree norecurse nounwind
; CHECK-LABEL: define {{[^@]+}}@bar
-; CHECK-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]], ptr nofree nonnull readonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR7:[0-9]+]] {
+; CHECK-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]], ptr nofree nonnull readonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR8:[0-9]+]] {
; CHECK-NEXT: br label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[I3:%.*]] = load atomic i8, ptr [[ARG1]] monotonic, align 1
@@ -285,7 +285,7 @@ bb6:
define void @foo1_singlethread(ptr %arg, ptr %arg1) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CHECK-LABEL: define {{[^@]+}}@foo1_singlethread
-; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR8:[0-9]+]] {
+; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]], ptr nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR9:[0-9]+]] {
; CHECK-NEXT: store i32 100, ptr [[ARG]], align 4
; CHECK-NEXT: fence syncscope("singlethread") release
; CHECK-NEXT: store atomic i8 1, ptr [[ARG1]] monotonic, align 1
@@ -300,7 +300,7 @@ define void @foo1_singlethread(ptr %arg, ptr %arg1) {
define void @bar_singlethread(ptr %arg, ptr %arg1) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind
; CHECK-LABEL: define {{[^@]+}}@bar_singlethread
-; CHECK-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]], ptr nofree nonnull readonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR9:[0-9]+]] {
+; CHECK-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]], ptr nofree nonnull readonly captures(none) dereferenceable(1) [[ARG1:%.*]]) #[[ATTR10:[0-9]+]] {
; CHECK-NEXT: br label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[I3:%.*]] = load atomic i8, ptr [[ARG1]] monotonic, align 1
@@ -334,8 +334,8 @@ declare void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 %len, i1 %isvolatile)
define i32 @memcpy_volatile(ptr %ptr1, ptr %ptr2) {
; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
; CHECK-LABEL: define {{[^@]+}}@memcpy_volatile
-; CHECK-SAME: (ptr nofree writeonly captures(none) [[PTR1:%.*]], ptr nofree readonly captures(none) [[PTR2:%.*]]) #[[ATTR12:[0-9]+]] {
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr nofree writeonly captures(none) [[PTR1]], ptr nofree readonly captures(none) [[PTR2]], i32 noundef 8, i1 noundef true) #[[ATTR21:[0-9]+]]
+; CHECK-SAME: (ptr nofree writeonly captures(none) [[PTR1:%.*]], ptr nofree readonly captures(none) [[PTR2:%.*]]) #[[ATTR13:[0-9]+]] {
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr nofree writeonly captures(none) [[PTR1]], ptr nofree readonly captures(none) [[PTR2]], i32 noundef 8, i1 noundef true) #[[ATTR22:[0-9]+]]
; CHECK-NEXT: ret i32 4
;
call void @llvm.memcpy.p0.p0.i32(ptr %ptr1, ptr %ptr2, i32 8, i1 true)
@@ -349,8 +349,8 @@ define i32 @memcpy_volatile(ptr %ptr1, ptr %ptr2) {
define i32 @memset_non_volatile(ptr %ptr1, i8 %val) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CHECK-LABEL: define {{[^@]+}}@memset_non_volatile
-; CHECK-SAME: (ptr nofree writeonly captures(none) [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR13:[0-9]+]] {
-; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr nofree writeonly captures(none) [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR22:[0-9]+]]
+; CHECK-SAME: (ptr nofree writeonly captures(none) [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR14:[0-9]+]] {
+; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr nofree writeonly captures(none) [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR23:[0-9]+]]
; CHECK-NEXT: ret i32 4
;
call void @llvm.memset.p0.i32(ptr %ptr1, i8 %val, i32 8, i1 false)
@@ -375,7 +375,7 @@ declare void @readnone_test() convergent readnone
define void @convergent_readnone() {
; CHECK: Function Attrs: memory(none)
; CHECK-LABEL: define {{[^@]+}}@convergent_readnone
-; CHECK-SAME: () #[[ATTR15:[0-9]+]] {
+; CHECK-SAME: () #[[ATTR16:[0-9]+]] {
; CHECK-NEXT: call void @readnone_test()
; CHECK-NEXT: ret void
;
@@ -392,7 +392,7 @@ declare void @llvm.x86.sse2.clflush(ptr)
define void @i_totally_sync() {
; CHECK: Function Attrs: nounwind
; CHECK-LABEL: define {{[^@]+}}@i_totally_sync
-; CHECK-SAME: () #[[ATTR16:[0-9]+]] {
+; CHECK-SAME: () #[[ATTR17:[0-9]+]] {
; CHECK-NEXT: tail call void @llvm.x86.sse2.clflush(ptr noundef nonnull align 4 dereferenceable(4) @a)
; CHECK-NEXT: ret void
;
@@ -407,7 +407,7 @@ declare float @llvm.cos.f32(float %val) readnone
define i32 @cos_test(float %x) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@cos_test
-; CHECK-SAME: (float [[X:%.*]]) #[[ATTR18:[0-9]+]] {
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR19:[0-9]+]] {
; CHECK-NEXT: ret i32 4
;
%i = call float @llvm.cos.f32(float %x)
@@ -417,8 +417,8 @@ define i32 @cos_test(float %x) {
define float @cos_test2(float %x) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@cos_test2
-; CHECK-SAME: (float [[X:%.*]]) #[[ATTR18]] {
-; CHECK-NEXT: [[C:%.*]] = call nofpclass(inf) float @llvm.cos.f32(float [[X]]) #[[ATTR23:[0-9]+]]
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR19]] {
+; CHECK-NEXT: [[C:%.*]] = call nofpclass(inf) float @llvm.cos.f32(float [[X]]) #[[ATTR24:[0-9]+]]
; CHECK-NEXT: ret float [[C]]
;
%c = call float @llvm.cos.f32(float %x)
@@ -429,8 +429,8 @@ declare void @unknown()
define void @nosync_convergent_callee_test() {
; CHECK: Function Attrs: nosync memory(none)
; CHECK-LABEL: define {{[^@]+}}@nosync_convergent_callee_test
-; CHECK-SAME: () #[[ATTR19:[0-9]+]] {
-; CHECK-NEXT: call void @unknown() #[[ATTR24:[0-9]+]]
+; CHECK-SAME: () #[[ATTR20:[0-9]+]] {
+; CHECK-NEXT: call void @unknown() #[[ATTR25:[0-9]+]]
; CHECK-NEXT: ret void
;
call void @unknown() nosync convergent readnone
@@ -440,28 +440,29 @@ define void @nosync_convergent_callee_test() {
; CHECK: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind optsize ssp willreturn memory(none) uwtable }
; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable }
; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable }
-; CHECK: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable }
-; CHECK: attributes #[[ATTR4]] = { noinline nounwind uwtable }
-; CHECK: attributes #[[ATTR5]] = { nofree noinline nounwind memory(argmem: readwrite) uwtable }
-; CHECK: attributes #[[ATTR6]] = { mustprogress nofree norecurse nounwind willreturn }
-; CHECK: attributes #[[ATTR7]] = { nofree norecurse nounwind }
-; CHECK: attributes #[[ATTR8]] = { mustprogress nofree norecurse nosync nounwind willreturn }
-; CHECK: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind }
-; CHECK: attributes #[[ATTR10:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
-; CHECK: attributes #[[ATTR11:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
-; CHECK: attributes #[[ATTR12]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
-; CHECK: attributes #[[ATTR13]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
-; CHECK: attributes #[[ATTR14:[0-9]+]] = { convergent memory(none) }
-; CHECK: attributes #[[ATTR15]] = { memory(none) }
-; CHECK: attributes #[[ATTR16]] = { nounwind }
-; CHECK: attributes #[[ATTR17:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
-; CHECK: attributes #[[ATTR18]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; CHECK: attributes #[[ATTR19]] = { nosync memory(none) }
-; CHECK: attributes #[[ATTR20]] = { nofree nounwind }
-; CHECK: attributes #[[ATTR21]] = { nofree willreturn }
-; CHECK: attributes #[[ATTR22]] = { nofree willreturn memory(write) }
-; CHECK: attributes #[[ATTR23]] = { nofree nosync willreturn }
-; CHECK: attributes #[[ATTR24]] = { convergent nosync memory(none) }
+; CHECK: attributes #[[ATTR3]] = { nofree norecurse nounwind memory(argmem: readwrite) uwtable }
+; CHECK: attributes #[[ATTR4]] = { noinline nosync nounwind uwtable }
+; CHECK: attributes #[[ATTR5]] = { noinline nounwind uwtable }
+; CHECK: attributes #[[ATTR6]] = { nofree noinline nounwind memory(argmem: readwrite) uwtable }
+; CHECK: attributes #[[ATTR7]] = { mustprogress nofree norecurse nounwind willreturn }
+; CHECK: attributes #[[ATTR8]] = { nofree norecurse nounwind }
+; CHECK: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn }
+; CHECK: attributes #[[ATTR10]] = { nofree norecurse nosync nounwind }
+; CHECK: attributes #[[ATTR11:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR12:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
+; CHECK: attributes #[[ATTR13]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR14]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
+; CHECK: attributes #[[ATTR15:[0-9]+]] = { convergent memory(none) }
+; CHECK: attributes #[[ATTR16]] = { memory(none) }
+; CHECK: attributes #[[ATTR17]] = { nounwind }
+; CHECK: attributes #[[ATTR18:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
+; CHECK: attributes #[[ATTR19]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
+; CHECK: attributes #[[ATTR20]] = { nosync memory(none) }
+; CHECK: attributes #[[ATTR21]] = { nofree nounwind }
+; CHECK: attributes #[[ATTR22]] = { nofree willreturn }
+; CHECK: attributes #[[ATTR23]] = { nofree willreturn memory(write) }
+; CHECK: attributes #[[ATTR24]] = { nofree nosync willreturn }
+; CHECK: attributes #[[ATTR25]] = { convergent nosync memory(none) }
;.
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CGSCC: {{.*}}
diff --git a/llvm/test/Transforms/Attributor/readattrs.ll b/llvm/test/Transforms/Attributor/readattrs.ll
index 1993472074ef8..307553412d022 100644
--- a/llvm/test/Transforms/Attributor/readattrs.ll
+++ b/llvm/test/Transforms/Attributor/readattrs.ll
@@ -206,13 +206,13 @@ define <4 x i32> @test12_2(<4 x ptr> %ptrs) {
}
define i32 @volatile_load(ptr %p) {
-; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; TUNIT: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@volatile_load
; TUNIT-SAME: (ptr nofree noundef align 4 [[P:%.*]]) #[[ATTR9:[0-9]+]] {
; TUNIT-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4
; TUNIT-NEXT: ret i32 [[LOAD]]
;
-; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; CGSCC: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@volatile_load
; CGSCC-SAME: (ptr nofree noundef align 4 [[P:%.*]]) #[[ATTR10:[0-9]+]] {
; CGSCC-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4
@@ -410,7 +410,7 @@ define i32 @read_only_constant_mem() {
; TUNIT: attributes #[[ATTR6:[0-9]+]] = { nounwind memory(argmem: read) }
; TUNIT: attributes #[[ATTR7]] = { nosync nounwind memory(argmem: read) }
; TUNIT: attributes #[[ATTR8]] = { nounwind memory(argmem: readwrite) }
-; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
+; TUNIT: attributes #[[ATTR9]] = { nofree norecurse nounwind memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR10]] = { nosync memory(none) }
; TUNIT: attributes #[[ATTR11]] = { nosync }
; TUNIT: attributes #[[ATTR12:[0-9]+]] = { nounwind memory(read) }
@@ -432,7 +432,7 @@ define i32 @read_only_constant_mem() {
; CGSCC: attributes #[[ATTR7:[0-9]+]] = { nounwind memory(argmem: read) }
; CGSCC: attributes #[[ATTR8]] = { nosync nounwind memory(argmem: read) }
; CGSCC: attributes #[[ATTR9]] = { nounwind memory(argmem: readwrite) }
-; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
+; CGSCC: attributes #[[ATTR10]] = { nofree norecurse nounwind memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR11]] = { nosync memory(none) }
; CGSCC: attributes #[[ATTR12]] = { nosync }
; CGSCC: attributes #[[ATTR13:[0-9]+]] = { nounwind memory(read) }
diff --git a/llvm/test/Transforms/Attributor/undefined_behavior.ll b/llvm/test/Transforms/Attributor/undefined_behavior.ll
index d102e4e5ce974..19100e33e5852 100644
--- a/llvm/test/Transforms/Attributor/undefined_behavior.ll
+++ b/llvm/test/Transforms/Attributor/undefined_behavior.ll
@@ -21,7 +21,7 @@ define void @load_wholly_unreachable() {
}
define void @load_wholly_unreachable_volatile() {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(none)
; CHECK-LABEL: define {{[^@]+}}@load_wholly_unreachable_volatile
; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: [[A:%.*]] = load volatile i32, ptr null, align 4
@@ -111,7 +111,7 @@ define void @store_wholly_unreachable() {
}
define void @store_wholly_unreachable_volatile() {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; CHECK: Function Attrs: nofree norecurse nounwind memory(none)
; CHECK-LABEL: define {{[^@]+}}@store_wholly_unreachable_volatile
; CHECK-SAME: () #[[ATTR1]] {
; CHECK-NEXT: store volatile i32 5, ptr null, align 4
@@ -168,7 +168,7 @@ define void @store_null_propagated() {
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@store_null_propagated
; CGSCC-SAME: () #[[ATTR5:[0-9]+]] {
-; CGSCC-NEXT: [[PTR:%.*]] = call noalias align 4294967296 ptr @ret_null() #[[ATTR10:[0-9]+]]
+; CGSCC-NEXT: [[PTR:%.*]] = call noalias align 4294967296 ptr @ret_null() #[[ATTR11:[0-9]+]]
; CGSCC-NEXT: ret void
;
%ptr = call ptr @ret_null()
@@ -179,24 +179,38 @@ define void @store_null_propagated() {
; -- AtomicRMW tests --
define void @atomicrmw_wholly_unreachable() {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
-; CHECK-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable
-; CHECK-SAME: () #[[ATTR1]] {
-; CHECK-NEXT: unreachable
+; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; TUNIT-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable
+; TUNIT-SAME: () #[[ATTR4:[0-9]+]] {
+; TUNIT-NEXT: unreachable
+;
+; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; CGSCC-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable
+; CGSCC-SAME: () #[[ATTR6:[0-9]+]] {
+; CGSCC-NEXT: unreachable
;
%a = atomicrmw add ptr null, i32 1 acquire
ret void
}
define void @atomicrmw_single_bb_unreachable(i1 %cond) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
-; CHECK-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable
-; CHECK-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
-; CHECK: t:
-; CHECK-NEXT: unreachable
-; CHECK: e:
-; CHECK-NEXT: ret void
+; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; TUNIT-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable
+; TUNIT-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] {
+; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
+; TUNIT: t:
+; TUNIT-NEXT: unreachable
+; TUNIT: e:
+; TUNIT-NEXT: ret void
+;
+; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; CGSCC-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable
+; CGSCC-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR6]] {
+; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
+; CGSCC: t:
+; CGSCC-NEXT: unreachable
+; CGSCC: e:
+; CGSCC-NEXT: ret void
;
br i1 %cond, label %t, label %e
t:
@@ -209,13 +223,13 @@ e:
define void @atomicrmw_null_pointer_is_defined() null_pointer_is_valid {
; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn
; TUNIT-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined
-; TUNIT-SAME: () #[[ATTR4:[0-9]+]] {
+; TUNIT-SAME: () #[[ATTR5:[0-9]+]] {
; TUNIT-NEXT: [[A:%.*]] = atomicrmw add ptr null, i32 1 acquire, align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn
; CGSCC-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined
-; CGSCC-SAME: () #[[ATTR6:[0-9]+]] {
+; CGSCC-SAME: () #[[ATTR7:[0-9]+]] {
; CGSCC-NEXT: [[A:%.*]] = atomicrmw add ptr null, i32 1 acquire, align 4
; CGSCC-NEXT: ret void
;
@@ -229,13 +243,13 @@ define void @atomicrmw_null_propagated() {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@atomicrmw_null_propagated
-; TUNIT-SAME: () #[[ATTR1]] {
+; TUNIT-SAME: () #[[ATTR4]] {
; TUNIT-NEXT: unreachable
;
; CGSCC: Function Attrs: mustprogress nofree nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@atomicrmw_null_propagated
-; CGSCC-SAME: () #[[ATTR7:[0-9]+]] {
-; CGSCC-NEXT: [[PTR:%.*]] = call noalias ptr @ret_null() #[[ATTR11:[0-9]+]]
+; CGSCC-SAME: () #[[ATTR8:[0-9]+]] {
+; CGSCC-NEXT: [[PTR:%.*]] = call noalias ptr @ret_null() #[[ATTR12:[0-9]+]]
; CGSCC-NEXT: [[A:%.*]] = atomicrmw add ptr [[PTR]], i32 1 acquire, align 4
; CGSCC-NEXT: ret void
;
@@ -247,24 +261,38 @@ define void @atomicrmw_null_propagated() {
; -- AtomicCmpXchg tests --
define void @atomiccmpxchg_wholly_unreachable() {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
-; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable
-; CHECK-SAME: () #[[ATTR1]] {
-; CHECK-NEXT: unreachable
+; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; TUNIT-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable
+; TUNIT-SAME: () #[[ATTR4]] {
+; TUNIT-NEXT: unreachable
+;
+; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; CGSCC-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable
+; CGSCC-SAME: () #[[ATTR6]] {
+; CGSCC-NEXT: unreachable
;
%a = cmpxchg ptr null, i32 2, i32 3 acq_rel monotonic
ret void
}
define void @atomiccmpxchg_single_bb_unreachable(i1 %cond) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
-; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable
-; CHECK-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
-; CHECK: t:
-; CHECK-NEXT: unreachable
-; CHECK: e:
-; CHECK-NEXT: ret void
+; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; TUNIT-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable
+; TUNIT-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] {
+; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
+; TUNIT: t:
+; TUNIT-NEXT: unreachable
+; TUNIT: e:
+; TUNIT-NEXT: ret void
+;
+; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
+; CGSCC-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable
+; CGSCC-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR6]] {
+; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
+; CGSCC: t:
+; CGSCC-NEXT: unreachable
+; CGSCC: e:
+; CGSCC-NEXT: ret void
;
br i1 %cond, label %t, label %e
t:
@@ -277,13 +305,13 @@ e:
define void @atomiccmpxchg_null_pointer_is_defined() null_pointer_is_valid {
; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn
; TUNIT-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined
-; TUNIT-SAME: () #[[ATTR4]] {
+; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: [[A:%.*]] = cmpxchg ptr null, i32 2, i32 3 acq_rel monotonic, align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn
; CGSCC-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined
-; CGSCC-SAME: () #[[ATTR6]] {
+; CGSCC-SAME: () #[[ATTR7]] {
; CGSCC-NEXT: [[A:%.*]] = cmpxchg ptr null, i32 2, i32 3 acq_rel monotonic, align 4
; CGSCC-NEXT: ret void
;
@@ -297,13 +325,13 @@ define void @atomiccmpxchg_null_propagated() {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated
-; TUNIT-SAME: () #[[ATTR1]] {
+; TUNIT-SAME: () #[[ATTR4]] {
; TUNIT-NEXT: unreachable
;
; CGSCC: Function Attrs: mustprogress nofree nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated
-; CGSCC-SAME: () #[[ATTR7]] {
-; CGSCC-NEXT: [[PTR:%.*]] = call noalias ptr @ret_null() #[[ATTR11]]
+; CGSCC-SAME: () #[[ATTR8]] {
+; CGSCC-NEXT: [[PTR:%.*]] = call noalias ptr @ret_null() #[[ATTR12]]
; CGSCC-NEXT: [[A:%.*]] = cmpxchg ptr [[PTR]], i32 2, i32 3 acq_rel monotonic, align 4
; CGSCC-NEXT: ret void
;
@@ -319,7 +347,7 @@ define void @atomiccmpxchg_null_propagated() {
define i32 @cond_br_on_undef() {
; TUNIT: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@cond_br_on_undef
-; TUNIT-SAME: () #[[ATTR5:[0-9]+]] {
+; TUNIT-SAME: () #[[ATTR6:[0-9]+]] {
; TUNIT-NEXT: unreachable
; TUNIT: t:
; TUNIT-NEXT: unreachable
@@ -328,7 +356,7 @@ define i32 @cond_br_on_undef() {
;
; CGSCC: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@cond_br_on_undef
-; CGSCC-SAME: () #[[ATTR8:[0-9]+]] {
+; CGSCC-SAME: () #[[ATTR9:[0-9]+]] {
; CGSCC-NEXT: unreachable
; CGSCC: t:
; CGSCC-NEXT: unreachable
@@ -382,7 +410,7 @@ define i1 @ret_undef() {
define void @cond_br_on_undef_interproc() {
; TUNIT: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc
-; TUNIT-SAME: () #[[ATTR5]] {
+; TUNIT-SAME: () #[[ATTR6]] {
; TUNIT-NEXT: unreachable
; TUNIT: t:
; TUNIT-NEXT: unreachable
@@ -392,7 +420,7 @@ define void @cond_br_on_undef_interproc() {
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc
; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT: [[COND:%.*]] = call i1 @ret_undef() #[[ATTR10]]
+; CGSCC-NEXT: [[COND:%.*]] = call i1 @ret_undef() #[[ATTR11]]
; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; CGSCC: t:
; CGSCC-NEXT: ret void
@@ -428,7 +456,7 @@ e:
define void @cond_br_on_undef_interproc2() {
; TUNIT: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2
-; TUNIT-SAME: () #[[ATTR5]] {
+; TUNIT-SAME: () #[[ATTR6]] {
; TUNIT-NEXT: unreachable
; TUNIT: t:
; TUNIT-NEXT: unreachable
@@ -438,7 +466,7 @@ define void @cond_br_on_undef_interproc2() {
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2
; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT: [[COND:%.*]] = call i1 @ret_undef2() #[[ATTR10]]
+; CGSCC-NEXT: [[COND:%.*]] = call i1 @ret_undef2() #[[ATTR11]]
; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; CGSCC: t:
; CGSCC-NEXT: ret void
@@ -458,7 +486,7 @@ e:
define i32 @cond_br_on_undef3() {
; TUNIT: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@cond_br_on_undef3
-; TUNIT-SAME: () #[[ATTR5]] {
+; TUNIT-SAME: () #[[ATTR6]] {
; TUNIT-NEXT: unreachable
; TUNIT: t:
; TUNIT-NEXT: unreachable
@@ -467,7 +495,7 @@ define i32 @cond_br_on_undef3() {
;
; CGSCC: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@cond_br_on_undef3
-; CGSCC-SAME: () #[[ATTR8]] {
+; CGSCC-SAME: () #[[ATTR9]] {
; CGSCC-NEXT: unreachable
; CGSCC: t:
; CGSCC-NEXT: unreachable
@@ -487,7 +515,7 @@ e:
define i32 @cond_br_on_undef_uninit() {
; TUNIT: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit
-; TUNIT-SAME: () #[[ATTR5]] {
+; TUNIT-SAME: () #[[ATTR6]] {
; TUNIT-NEXT: unreachable
; TUNIT: t:
; TUNIT-NEXT: unreachable
@@ -496,7 +524,7 @@ define i32 @cond_br_on_undef_uninit() {
;
; CGSCC: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit
-; CGSCC-SAME: () #[[ATTR8]] {
+; CGSCC-SAME: () #[[ATTR9]] {
; CGSCC-NEXT: unreachable
; CGSCC: t:
; CGSCC-NEXT: unreachable
@@ -548,7 +576,7 @@ define i32 @foo() {
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@foo
; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT: [[X:%.*]] = call noundef i32 @callee() #[[ATTR10]]
+; CGSCC-NEXT: [[X:%.*]] = call noundef i32 @callee() #[[ATTR11]]
; CGSCC-NEXT: ret i32 [[X]]
;
%X = call i32 @callee(i1 false, ptr null)
@@ -562,13 +590,13 @@ define i32 @foo() {
define void @arg_nonnull_1(ptr nonnull %a) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; TUNIT-LABEL: define {{[^@]+}}@arg_nonnull_1
-; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
+; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR7:[0-9]+]] {
; TUNIT-NEXT: store i32 0, ptr [[A]], align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CGSCC-LABEL: define {{[^@]+}}@arg_nonnull_1
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR9:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR10:[0-9]+]] {
; CGSCC-NEXT: store i32 0, ptr [[A]], align 4
; CGSCC-NEXT: ret void
;
@@ -579,13 +607,13 @@ define void @arg_nonnull_1(ptr nonnull %a) {
define void @arg_nonnull_1_noundef_1(ptr nonnull noundef %a) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; TUNIT-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1
-; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR6]] {
+; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR7]] {
; TUNIT-NEXT: store i32 0, ptr [[A]], align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CGSCC-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR9]] {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR10]] {
; CGSCC-NEXT: store i32 0, ptr [[A]], align 4
; CGSCC-NEXT: ret void
;
@@ -596,7 +624,7 @@ define void @arg_nonnull_1_noundef_1(ptr nonnull noundef %a) {
define void @arg_nonnull_12(ptr nonnull %a, ptr nonnull %b, ptr %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; TUNIT-LABEL: define {{[^@]+}}@arg_nonnull_12
-; TUNIT-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR6]] {
+; TUNIT-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR7]] {
; TUNIT-NEXT: [[D:%.*]] = icmp eq ptr [[C]], null
; TUNIT-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; TUNIT: t:
@@ -610,7 +638,7 @@ define void @arg_nonnull_12(ptr nonnull %a, ptr nonnull %b, ptr %c) {
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CGSCC-LABEL: define {{[^@]+}}@arg_nonnull_12
-; CGSCC-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR9]] {
+; CGSCC-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR10]] {
; CGSCC-NEXT: [[D:%.*]] = icmp eq ptr [[C]], null
; CGSCC-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; CGSCC: t:
@@ -637,7 +665,7 @@ ret:
define void @arg_nonnull_12_noundef_2(ptr nonnull %a, ptr noundef nonnull %b, ptr %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; TUNIT-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2
-; TUNIT-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree noundef nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR6]] {
+; TUNIT-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree noundef nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR7]] {
; TUNIT-NEXT: [[D:%.*]] = icmp eq ptr [[C]], null
; TUNIT-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; TUNIT: t:
@@ -651,7 +679,7 @@ define void @arg_nonnull_12_noundef_2(ptr nonnull %a, ptr noundef nonnull %b, pt
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CGSCC-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2
-; CGSCC-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree noundef nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR9]] {
+; CGSCC-SAME: (ptr nofree nonnull writeonly captures(none) [[A:%.*]], ptr nofree noundef nonnull writeonly captures(none) [[B:%.*]], ptr nofree writeonly [[C:%.*]]) #[[ATTR10]] {
; CGSCC-NEXT: [[D:%.*]] = icmp eq ptr [[C]], null
; CGSCC-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; CGSCC: t:
@@ -747,8 +775,8 @@ define void @arg_nonnull_violation3_1(i1 %c) {
; TUNIT-NEXT: [[PTR:%.*]] = alloca i32, align 4
; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; TUNIT: t:
-; TUNIT-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7:[0-9]+]]
-; TUNIT-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR7]]
+; TUNIT-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR8:[0-9]+]]
+; TUNIT-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR8]]
; TUNIT-NEXT: unreachable
; TUNIT: f:
; TUNIT-NEXT: unreachable
@@ -761,8 +789,8 @@ define void @arg_nonnull_violation3_1(i1 %c) {
; CGSCC-NEXT: [[PTR:%.*]] = alloca i32, align 4
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CGSCC: t:
-; CGSCC-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR12:[0-9]+]]
-; CGSCC-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR12]]
+; CGSCC-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR13:[0-9]+]]
+; CGSCC-NEXT: call void @arg_nonnull_12(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR13]]
; CGSCC-NEXT: unreachable
; CGSCC: f:
; CGSCC-NEXT: unreachable
@@ -794,8 +822,8 @@ define void @arg_nonnull_violation3_2(i1 %c) {
; TUNIT-NEXT: [[PTR:%.*]] = alloca i32, align 4
; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; TUNIT: t:
-; TUNIT-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7]]
-; TUNIT-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR7]]
+; TUNIT-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR8]]
+; TUNIT-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR8]]
; TUNIT-NEXT: unreachable
; TUNIT: f:
; TUNIT-NEXT: unreachable
@@ -808,8 +836,8 @@ define void @arg_nonnull_violation3_2(i1 %c) {
; CGSCC-NEXT: [[PTR:%.*]] = alloca i32, align 4
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CGSCC: t:
-; CGSCC-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR12]]
-; CGSCC-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR12]]
+; CGSCC-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR13]]
+; CGSCC-NEXT: call void @arg_nonnull_12_noundef_2(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[PTR]], ptr nofree noundef writeonly null) #[[ATTR13]]
; CGSCC-NEXT: unreachable
; CGSCC: f:
; CGSCC-NEXT: unreachable
@@ -1026,7 +1054,7 @@ define noundef i32 @assumed_undef_is_ok_caller(i1 %c) {
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@assumed_undef_is_ok_caller
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT: [[CALL:%.*]] = call i32 @assumed_undef_is_ok(i1 noundef [[C]]) #[[ATTR10]]
+; CGSCC-NEXT: [[CALL:%.*]] = call i32 @assumed_undef_is_ok(i1 noundef [[C]]) #[[ATTR11]]
; CGSCC-NEXT: ret i32 [[CALL]]
;
%call = call i32 @assumed_undef_is_ok(i1 %c, i32 undef)
@@ -1035,25 +1063,27 @@ define noundef i32 @assumed_undef_is_ok_caller(i1 %c) {
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nounwind willreturn memory(none) }
+; TUNIT: attributes #[[ATTR1]] = { nofree norecurse nounwind memory(none) }
; TUNIT: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(write) }
-; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn }
-; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) }
-; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
-; TUNIT: attributes #[[ATTR7]] = { nofree nosync nounwind willreturn memory(write) }
+; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nounwind willreturn memory(none) }
+; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn }
+; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) }
+; TUNIT: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
+; TUNIT: attributes #[[ATTR8]] = { nofree nosync nounwind willreturn memory(write) }
;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nounwind willreturn memory(none) }
+; CGSCC: attributes #[[ATTR1]] = { nofree norecurse nounwind memory(none) }
; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(write) }
; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree nosync nounwind willreturn memory(write) }
-; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn }
-; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree nounwind willreturn }
-; CGSCC: attributes #[[ATTR8]] = { mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) }
-; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
-; CGSCC: attributes #[[ATTR10]] = { nofree nosync willreturn }
-; CGSCC: attributes #[[ATTR11]] = { nofree willreturn }
-; CGSCC: attributes #[[ATTR12]] = { nofree nounwind willreturn memory(write) }
+; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nounwind willreturn memory(none) }
+; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nounwind null_pointer_is_valid willreturn }
+; CGSCC: attributes #[[ATTR8]] = { mustprogress nofree nounwind willreturn }
+; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) }
+; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
+; CGSCC: attributes #[[ATTR11]] = { nofree nosync willreturn }
+; CGSCC: attributes #[[ATTR12]] = { nofree willreturn }
+; CGSCC: attributes #[[ATTR13]] = { nofree nounwind willreturn memory(write) }
;.
diff --git a/llvm/test/Transforms/Attributor/value-simplify-local-remote.ll b/llvm/test/Transforms/Attributor/value-simplify-local-remote.ll
index 75ab54059f302..3a4f2ba0bc415 100644
--- a/llvm/test/Transforms/Attributor/value-simplify-local-remote.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify-local-remote.ll
@@ -459,7 +459,7 @@ define double @t4(ptr %this, ptr %this.addr, ptr %this1) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[THIS_ADDR1:%.*]] = alloca ptr, i32 0, align 8
; TUNIT-NEXT: store ptr [[THIS]], ptr [[THIS]], align 8
-; TUNIT-NEXT: [[CALL:%.*]] = call [[S:%.*]] @[[T4A:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]](ptr nofree noundef nonnull writeonly align 8 dereferenceable(8) [[THIS]]) #[[ATTR5]]
+; TUNIT-NEXT: [[CALL:%.*]] = call [[S:%.*]] @[[T4A:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]](ptr nofree noundef nonnull writeonly align 8 dereferenceable(8) [[THIS]]) #[[ATTR3]]
; TUNIT-NEXT: ret double 0.000000e+00
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
@@ -489,7 +489,7 @@ define internal %S @t4a(ptr %this) {
; TUNIT-NEXT: [[RETVAL:%.*]] = alloca [[S:%.*]], i32 0, align 8
; TUNIT-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, i32 0, align 8
; TUNIT-NEXT: store ptr [[THIS]], ptr [[THIS]], align 8
-; TUNIT-NEXT: call void @t4b(ptr noalias nofree noundef nonnull writeonly align 8 captures(none) [[RETVAL]]) #[[ATTR5]]
+; TUNIT-NEXT: call void @t4b(ptr noalias nofree noundef nonnull writeonly align 8 captures(none) [[RETVAL]]) #[[ATTR3]]
; TUNIT-NEXT: ret [[S]] undef
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
@@ -523,7 +523,7 @@ define internal void @t4b(ptr %this, ptr %data) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, i32 0, align 8
; TUNIT-NEXT: [[DATA_ADDR:%.*]] = alloca ptr, i32 0, align 8
-; TUNIT-NEXT: call void @t4c(ptr noalias nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[THIS]]) #[[ATTR5]]
+; TUNIT-NEXT: call void @t4c(ptr noalias nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[THIS]]) #[[ATTR3]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: write)
diff --git a/llvm/test/Transforms/Attributor/value-simplify-reachability.ll b/llvm/test/Transforms/Attributor/value-simplify-reachability.ll
index a1b9d9adc4aab..1a5ffec848cd5 100644
--- a/llvm/test/Transforms/Attributor/value-simplify-reachability.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify-reachability.ll
@@ -884,7 +884,7 @@ define i32 @two_calls() {
; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn }
; TUNIT: attributes #[[ATTR11:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR12]] = { nosync nounwind memory(write) }
-; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR13]] = { nofree norecurse nosync nounwind willreturn }
;.
; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
; CGSCC: attributes #[[ATTR1:[0-9]+]] = { nocallback nosync }
diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll
index 981964ec1efed..51c9f77d68449 100644
--- a/llvm/test/Transforms/Attributor/value-simplify.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify.ll
@@ -1684,7 +1684,7 @@ define i32 @readExtInitZeroInit() {
; TUNIT: attributes #[[ATTR10]] = { nofree willreturn }
; TUNIT: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn memory(write) }
; TUNIT: attributes #[[ATTR12]] = { nofree willreturn memory(readwrite) }
-; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR13]] = { nofree norecurse nosync nounwind willreturn }
; TUNIT: attributes #[[ATTR14]] = { nosync }
; TUNIT: attributes #[[ATTR15]] = { nosync nounwind memory(read) }
; TUNIT: attributes #[[ATTR16]] = { nounwind memory(write) }
diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
index 421ef601d0b85..b5577ad505ca6 100644
--- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -46,7 +46,7 @@ define void @c3(ptr %q) {
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; ATTRIBUTOR-LABEL: define void @c3
; ATTRIBUTOR-SAME: (ptr nofree writeonly [[Q:%.*]]) #[[ATTR1]] {
-; ATTRIBUTOR-NEXT: call void @c2(ptr nofree writeonly [[Q]]) #[[ATTR21:[0-9]+]]
+; ATTRIBUTOR-NEXT: call void @c2(ptr nofree writeonly [[Q]]) #[[ATTR22:[0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
call void @c2(ptr %q)
@@ -232,7 +232,7 @@ define i1 @c7(ptr %q, i32 %bitno) {
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; ATTRIBUTOR-LABEL: define i1 @c7
; ATTRIBUTOR-SAME: (ptr nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR2]] {
-; ATTRIBUTOR-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR22:[0-9]+]]
+; ATTRIBUTOR-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR23:[0-9]+]]
; ATTRIBUTOR-NEXT: [[VAL:%.*]] = load i1, ptr [[PTR]], align 1
; ATTRIBUTOR-NEXT: ret i1 [[VAL]]
;
@@ -337,7 +337,7 @@ define void @nc2(ptr %p, ptr %q) {
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; ATTRIBUTOR-LABEL: define void @nc2
; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR5]] {
-; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr nofree [[Q]], ptr nofree captures(none) [[P]], i1 false) #[[ATTR23:[0-9]+]]
+; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr nofree [[Q]], ptr nofree captures(none) [[P]], i1 false) #[[ATTR24:[0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
%1 = call i32 @nc1(ptr %q, ptr %p, i1 0) ; <i32> [#uses=0]
@@ -389,7 +389,7 @@ define void @readonly_nounwind_willreturn(ptr %p) {
; ATTRIBUTOR: Function Attrs: mustprogress nosync nounwind willreturn memory(read)
; ATTRIBUTOR-LABEL: define void @readonly_nounwind_willreturn
; ATTRIBUTOR-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR9:[0-9]+]] {
-; ATTRIBUTOR-NEXT: call void @external_willreturn(ptr readonly captures(none) [[P]]) #[[ATTR24:[0-9]+]]
+; ATTRIBUTOR-NEXT: call void @external_willreturn(ptr readonly captures(none) [[P]]) #[[ATTR25:[0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
call void @external_willreturn(ptr %p)
@@ -705,9 +705,9 @@ define void @test_volatile(ptr %x) {
; FNATTRS-NEXT: store volatile i32 0, ptr [[GEP]], align 4
; FNATTRS-NEXT: ret void
;
-; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; ATTRIBUTOR-LABEL: define void @test_volatile
-; ATTRIBUTOR-SAME: (ptr nofree [[X:%.*]]) #[[ATTR11]] {
+; ATTRIBUTOR-SAME: (ptr nofree [[X:%.*]]) #[[ATTR12:[0-9]+]] {
; ATTRIBUTOR-NEXT: entry:
; ATTRIBUTOR-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[X]], i64 1
; ATTRIBUTOR-NEXT: store volatile i32 0, ptr [[GEP]], align 4
@@ -730,9 +730,9 @@ define void @nocaptureLaunder(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
; ATTRIBUTOR-LABEL: define void @nocaptureLaunder
-; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]]) #[[ATTR12:[0-9]+]] {
+; ATTRIBUTOR-SAME: (ptr nofree captures(none) [[P:%.*]]) #[[ATTR13:[0-9]+]] {
; ATTRIBUTOR-NEXT: entry:
-; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) #[[ATTR25:[0-9]+]]
+; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) #[[ATTR26:[0-9]+]]
; ATTRIBUTOR-NEXT: store i8 42, ptr [[B]], align 1
; ATTRIBUTOR-NEXT: ret void
;
@@ -754,7 +754,7 @@ define void @captureLaunder(ptr %p) {
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; ATTRIBUTOR-LABEL: define void @captureLaunder
; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {
-; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) #[[ATTR25]]
+; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) #[[ATTR26]]
; ATTRIBUTOR-NEXT: store ptr [[B]], ptr @g2, align 8
; ATTRIBUTOR-NEXT: ret void
;
@@ -774,9 +774,9 @@ define void @nocaptureStrip(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; ATTRIBUTOR-LABEL: define void @nocaptureStrip
-; ATTRIBUTOR-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR13:[0-9]+]] {
+; ATTRIBUTOR-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR14:[0-9]+]] {
; ATTRIBUTOR-NEXT: entry:
-; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) #[[ATTR22]]
+; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) #[[ATTR23]]
; ATTRIBUTOR-NEXT: store i8 42, ptr [[B]], align 1
; ATTRIBUTOR-NEXT: ret void
;
@@ -798,7 +798,7 @@ define void @captureStrip(ptr %p) {
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; ATTRIBUTOR-LABEL: define void @captureStrip
; ATTRIBUTOR-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR1]] {
-; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) #[[ATTR22]]
+; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) #[[ATTR23]]
; ATTRIBUTOR-NEXT: store ptr [[B]], ptr @g3, align 8
; ATTRIBUTOR-NEXT: ret void
;
@@ -947,7 +947,7 @@ define i1 @inboundsGEPICmpNullPointerDefined(ptr %x) null_pointer_is_valid {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
; ATTRIBUTOR-LABEL: define i1 @inboundsGEPICmpNullPointerDefined
-; ATTRIBUTOR-SAME: (ptr nofree readnone [[X:%.*]]) #[[ATTR14:[0-9]+]] {
+; ATTRIBUTOR-SAME: (ptr nofree readnone [[X:%.*]]) #[[ATTR15:[0-9]+]] {
; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[X]], i32 5
; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
; ATTRIBUTOR-NEXT: ret i1 [[TMP2]]
@@ -983,7 +983,7 @@ define i1 @captureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) n
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
; ATTRIBUTOR-LABEL: define i1 @captureDereferenceableOrNullICmp
-; ATTRIBUTOR-SAME: (ptr nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR14]] {
+; ATTRIBUTOR-SAME: (ptr nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR15]] {
; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
; ATTRIBUTOR-NEXT: ret i1 [[TMP1]]
;
@@ -1038,8 +1038,8 @@ define void @readnone_indirec(ptr %f, ptr %p) {
;
; ATTRIBUTOR: Function Attrs: nosync memory(none)
; ATTRIBUTOR-LABEL: define void @readnone_indirec
-; ATTRIBUTOR-SAME: (ptr nofree nonnull readnone captures(none) [[F:%.*]], ptr readnone [[P:%.*]]) #[[ATTR15:[0-9]+]] {
-; ATTRIBUTOR-NEXT: call void [[F]](ptr [[P]]) #[[ATTR26:[0-9]+]]
+; ATTRIBUTOR-SAME: (ptr nofree nonnull readnone captures(none) [[F:%.*]], ptr readnone [[P:%.*]]) #[[ATTR16:[0-9]+]] {
+; ATTRIBUTOR-NEXT: call void [[F]](ptr [[P]]) #[[ATTR27:[0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
call void %f(ptr %p) readnone
@@ -1301,10 +1301,10 @@ define void @addr_only_scc(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
; ATTRIBUTOR-LABEL: define void @addr_only_scc
-; ATTRIBUTOR-SAME: (ptr nofree nonnull [[P:%.*]]) #[[ATTR16:[0-9]+]] {
+; ATTRIBUTOR-SAME: (ptr nofree nonnull [[P:%.*]]) #[[ATTR17:[0-9]+]] {
; ATTRIBUTOR-NEXT: [[V:%.*]] = load i8, ptr [[P]], align 1
; ATTRIBUTOR-NEXT: store i8 [[V]], ptr @g, align 1
-; ATTRIBUTOR-NEXT: call void @addr_only_scc2(ptr nofree nonnull [[P]]) #[[ATTR16]]
+; ATTRIBUTOR-NEXT: call void @addr_only_scc2(ptr nofree nonnull [[P]]) #[[ATTR17]]
; ATTRIBUTOR-NEXT: ret void
;
%v = load i8, ptr %p
@@ -1327,11 +1327,11 @@ define void @addr_only_scc2(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
; ATTRIBUTOR-LABEL: define void @addr_only_scc2
-; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR16]] {
+; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR17]] {
; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp ne ptr [[P]], null
; ATTRIBUTOR-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[EXIT:%.*]]
; ATTRIBUTOR: if:
-; ATTRIBUTOR-NEXT: call void @addr_only_scc(ptr nofree [[P]]) #[[ATTR16]]
+; ATTRIBUTOR-NEXT: call void @addr_only_scc(ptr nofree [[P]]) #[[ATTR17]]
; ATTRIBUTOR-NEXT: br label [[EXIT]]
; ATTRIBUTOR: exit:
; ATTRIBUTOR-NEXT: ret void
@@ -1356,8 +1356,8 @@ define void @assume_align(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
; ATTRIBUTOR-LABEL: define void @assume_align
-; ATTRIBUTOR-SAME: (ptr nofree readnone captures(none) [[P:%.*]]) #[[ATTR17:[0-9]+]] {
-; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #[[ATTR27:[0-9]+]] [ "align"(ptr [[P]], i64 8) ]
+; ATTRIBUTOR-SAME: (ptr nofree readnone captures(none) [[P:%.*]]) #[[ATTR18:[0-9]+]] {
+; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #[[ATTR28:[0-9]+]] [ "align"(ptr [[P]], i64 8) ]
; ATTRIBUTOR-NEXT: ret void
;
call void @llvm.assume(i1 true) ["align"(ptr %p, i64 8)]
@@ -1373,8 +1373,8 @@ define void @assume_dereferenceable(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
; ATTRIBUTOR-LABEL: define void @assume_dereferenceable
-; ATTRIBUTOR-SAME: (ptr nofree nonnull readnone captures(none) [[P:%.*]]) #[[ATTR17]] {
-; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #[[ATTR27]] [ "dereferenceable"(ptr [[P]], i64 8) ]
+; ATTRIBUTOR-SAME: (ptr nofree nonnull readnone captures(none) [[P:%.*]]) #[[ATTR18]] {
+; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #[[ATTR28]] [ "dereferenceable"(ptr [[P]], i64 8) ]
; ATTRIBUTOR-NEXT: ret void
;
call void @llvm.assume(i1 true) ["dereferenceable"(ptr %p, i64 8)]
@@ -1390,8 +1390,8 @@ define void @assume_nonnull(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
; ATTRIBUTOR-LABEL: define void @assume_nonnull
-; ATTRIBUTOR-SAME: (ptr nofree nonnull readnone captures(none) [[P:%.*]]) #[[ATTR17]] {
-; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #[[ATTR27]] [ "nonnull"(ptr [[P]]) ]
+; ATTRIBUTOR-SAME: (ptr nofree nonnull readnone captures(none) [[P:%.*]]) #[[ATTR18]] {
+; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #[[ATTR28]] [ "nonnull"(ptr [[P]]) ]
; ATTRIBUTOR-NEXT: ret void
;
call void @llvm.assume(i1 true) ["nonnull"(ptr %p)]
@@ -1407,7 +1407,7 @@ define void @captures_metadata_address_is_null(ptr %x, ptr %y) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; ATTRIBUTOR-LABEL: define void @captures_metadata_address_is_null
-; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR13]] {
+; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR14]] {
; ATTRIBUTOR-NEXT: store ptr [[X]], ptr [[Y]], align 8, !captures [[META0:![0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
@@ -1424,7 +1424,7 @@ define void @captures_metadata_address(ptr %x, ptr %y) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; ATTRIBUTOR-LABEL: define void @captures_metadata_address
-; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR13]] {
+; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR14]] {
; ATTRIBUTOR-NEXT: store ptr [[X]], ptr [[Y]], align 8, !captures [[META1:![0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
@@ -1441,7 +1441,7 @@ define void @captures_metadata_address_read_provenance(ptr %x, ptr %y) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; ATTRIBUTOR-LABEL: define void @captures_metadata_address_read_provenance
-; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR13]] {
+; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR14]] {
; ATTRIBUTOR-NEXT: store ptr [[X]], ptr [[Y]], align 8, !captures [[META2:![0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
@@ -1458,7 +1458,7 @@ define void @captures_metadata_provenance(ptr %x, ptr %y) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; ATTRIBUTOR-LABEL: define void @captures_metadata_provenance
-; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR13]] {
+; ATTRIBUTOR-SAME: (ptr nofree writeonly [[X:%.*]], ptr nofree nonnull writeonly captures(none) [[Y:%.*]]) #[[ATTR14]] {
; ATTRIBUTOR-NEXT: store ptr [[X]], ptr [[Y]], align 8, !captures [[META3:![0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
diff --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index bbfe2cd5d74e3..cc377d4cdf6b2 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -352,13 +352,13 @@ define i32 @volatile_load(ptr %p) {
; FNATTRS-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4
; FNATTRS-NEXT: ret i32 [[LOAD]]
;
-; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; ATTRIBUTOR-LABEL: define {{[^@]+}}@volatile_load
; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR9:[0-9]+]] {
; ATTRIBUTOR-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4
; ATTRIBUTOR-NEXT: ret i32 [[LOAD]]
;
-; ATTRIBUTOR-CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; ATTRIBUTOR-CGSCC: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; ATTRIBUTOR-CGSCC-LABEL: define {{[^@]+}}@volatile_load
; ATTRIBUTOR-CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR10:[0-9]+]] {
; ATTRIBUTOR-CGSCC-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4
diff --git a/llvm/test/Transforms/FunctionAttrs/writeonly.ll b/llvm/test/Transforms/FunctionAttrs/writeonly.ll
index e00ed9e0f2293..27fd7fca28601 100644
--- a/llvm/test/Transforms/FunctionAttrs/writeonly.ll
+++ b/llvm/test/Transforms/FunctionAttrs/writeonly.ll
@@ -151,7 +151,7 @@ define void @test_volatile(ptr %p) {
; FNATTRS-NEXT: store volatile i8 0, ptr [[P]], align 1
; FNATTRS-NEXT: ret void
;
-; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite)
; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_volatile
; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR6:[0-9]+]] {
; ATTRIBUTOR-NEXT: store volatile i8 0, ptr [[P]], align 1
@@ -170,7 +170,7 @@ define void @test_atomicrmw(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_atomicrmw
-; ATTRIBUTOR-SAME: (ptr nofree nonnull captures(none) [[P:%.*]]) #[[ATTR6]] {
+; ATTRIBUTOR-SAME: (ptr nofree nonnull captures(none) [[P:%.*]]) #[[ATTR7:[0-9]+]] {
; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i8 0 seq_cst, align 1
; ATTRIBUTOR-NEXT: ret void
;
@@ -189,7 +189,7 @@ define void @test_ptrmask(ptr %p) {
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_ptrmask
; ATTRIBUTOR-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR3]] {
-; ATTRIBUTOR-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -5) #[[ATTR9:[0-9]+]]
+; ATTRIBUTOR-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -5) #[[ATTR10:[0-9]+]]
; ATTRIBUTOR-NEXT: store i8 0, ptr [[MASK]], align 1
; ATTRIBUTOR-NEXT: ret void
;
@@ -224,8 +224,8 @@ define void @direct2(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: memory(write)
; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct2
-; ATTRIBUTOR-SAME: (ptr writeonly [[P:%.*]]) #[[ATTR8:[0-9]+]] {
-; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr [[P]]) #[[ATTR8]]
+; ATTRIBUTOR-SAME: (ptr writeonly [[P:%.*]]) #[[ATTR9:[0-9]+]] {
+; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr [[P]]) #[[ATTR9]]
; ATTRIBUTOR-NEXT: ret void
;
call void @direct2_callee(ptr %p)
@@ -242,8 +242,8 @@ define void @direct2b(ptr %p) {
;
; ATTRIBUTOR: Function Attrs: memory(write)
; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct2b
-; ATTRIBUTOR-SAME: (ptr writeonly captures(none) [[P:%.*]]) #[[ATTR8]] {
-; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr writeonly captures(none) [[P]]) #[[ATTR8]]
+; ATTRIBUTOR-SAME: (ptr writeonly captures(none) [[P:%.*]]) #[[ATTR9]] {
+; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr writeonly captures(none) [[P]]) #[[ATTR9]]
; ATTRIBUTOR-NEXT: ret void
;
call void @direct2_callee(ptr nocapture %p)
@@ -331,8 +331,8 @@ define void @fptr_test3(ptr %p, ptr %f) {
;
; ATTRIBUTOR: Function Attrs: memory(write)
; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test3
-; ATTRIBUTOR-SAME: (ptr writeonly captures(none) [[P:%.*]], ptr nofree nonnull writeonly captures(none) [[F:%.*]]) #[[ATTR8]] {
-; ATTRIBUTOR-NEXT: call void [[F]](ptr captures(none) [[P]]) #[[ATTR8]]
+; ATTRIBUTOR-SAME: (ptr writeonly captures(none) [[P:%.*]], ptr nofree nonnull writeonly captures(none) [[F:%.*]]) #[[ATTR9]] {
+; ATTRIBUTOR-NEXT: call void [[F]](ptr captures(none) [[P]]) #[[ATTR9]]
; ATTRIBUTOR-NEXT: ret void
;
call void %f(ptr nocapture %p) writeonly
@@ -347,7 +347,7 @@ define void @test_argmem_none_callee(ptr %p) {
;
; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_argmem_none_callee
; ATTRIBUTOR-SAME: (ptr captures(none) [[P:%.*]]) {
-; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr captures(none) [[P]]) #[[ATTR10:[0-9]+]]
+; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr captures(none) [[P]]) #[[ATTR11:[0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
call void @direct1_callee(ptr nocapture %p) memory(readwrite, argmem: none)
@@ -362,7 +362,7 @@ define void @test_argmem_read_callee(ptr %p) {
;
; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_argmem_read_callee
; ATTRIBUTOR-SAME: (ptr captures(none) [[P:%.*]]) {
-; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr captures(none) [[P]]) #[[ATTR11:[0-9]+]]
+; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr captures(none) [[P]]) #[[ATTR12:[0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
call void @direct1_callee(ptr nocapture %p) memory(readwrite, argmem: read)
@@ -377,7 +377,7 @@ define void @test_argmem_write_callee(ptr %p) {
;
; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_argmem_write_callee
; ATTRIBUTOR-SAME: (ptr captures(none) [[P:%.*]]) {
-; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr captures(none) [[P]]) #[[ATTR12:[0-9]+]]
+; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr captures(none) [[P]]) #[[ATTR13:[0-9]+]]
; ATTRIBUTOR-NEXT: ret void
;
call void @direct1_callee(ptr nocapture %p) memory(readwrite, argmem: write)
>From f454fb69eb3bb349e84650d17423984fd2187775 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 21 Apr 2026 13:13:23 +0200
Subject: [PATCH 3/3] Add "speculatable" to atomic doc
---
llvm/docs/Atomics.rst | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/docs/Atomics.rst b/llvm/docs/Atomics.rst
index 1bcd864dd15bf..ad3ee1824db42 100644
--- a/llvm/docs/Atomics.rst
+++ b/llvm/docs/Atomics.rst
@@ -40,8 +40,9 @@ which ensures that every volatile load and store happens and is performed in the
stated order. A couple examples: if a SequentiallyConsistent store is
immediately followed by another SequentiallyConsistent store to the same
address, the first store can be erased. This transformation is not allowed for a
-pair of volatile stores. On the other hand, a non-volatile non-atomic load can
-be moved across a volatile load freely, but not an Acquire load.
+pair of volatile stores. On the other hand, a speculatable non-volatile
+non-atomic load can be moved across a volatile load freely, but not an Acquire
+load.
This document is intended to guide anyone writing a frontend
for LLVM or working on optimization passes for LLVM on how to deal
More information about the llvm-commits
mailing list