[llvm] [FunctionAttrs] Add `errno` inference logic (PR #129067)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 27 07:21:14 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Antonio Frighetto (antoniofrighetto)
<details>
<summary>Changes</summary>
Refine errnomem for a given memory location. In particular, accesses to `__errno_location` et alia do alias errno, whereas locally-invariant memory should never alias errno. Likewise, memory accesses larger than `sizeof(int)` should not alias errno.
---
Full diff: https://github.com/llvm/llvm-project/pull/129067.diff
7 Files Affected:
- (modified) llvm/lib/Transforms/IPO/FunctionAttrs.cpp (+32-2)
- (modified) llvm/test/Transforms/FunctionAttrs/argmemonly.ll (+7-7)
- (added) llvm/test/Transforms/FunctionAttrs/errnomemnone.ll (+30)
- (modified) llvm/test/Transforms/FunctionAttrs/initializes.ll (+12-9)
- (added) llvm/test/Transforms/FunctionAttrs/read-write-errnomem.ll (+71)
- (modified) llvm/test/Transforms/FunctionAttrs/readattrs.ll (+6-4)
- (modified) llvm/test/Transforms/PhaseOrdering/pr95152.ll (+1-1)
``````````diff
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index a63e38a7d98ad..bebcb4057acba 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -118,16 +118,31 @@ static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc,
ModRefInfo MR, AAResults &AAR) {
// Ignore accesses to known-invariant or local memory.
MR &= AAR.getModRefInfoMask(Loc, /*IgnoreLocal=*/true);
- if (isNoModRef(MR))
+ if (isNoModRef(MR)) {
+ // Mask out errno, can never alias this known-invariant memory location.
+ ME -= ME.errnoMemOnly();
return;
+ }
const Value *UO = getUnderlyingObjectAggressive(Loc.Ptr);
- if (isa<AllocaInst>(UO))
+ if (isa<AllocaInst>(UO)) {
+ ME -= ME.errnoMemOnly();
return;
+ }
if (isa<Argument>(UO)) {
ME |= MemoryEffects::argMemOnly(MR);
return;
}
+ if (auto *CI = dyn_cast<CallInst>(UO)) {
+ if (auto *Callee = CI->getCalledFunction()) {
+ static constexpr auto ErrnoFnNames = {"__errno_location", "_errno",
+ "__errno", "___errno"};
+ if (is_contained(ErrnoFnNames, Callee->getName())) {
+ ME |= MemoryEffects::errnoMemOnly(MR);
+ return;
+ }
+ }
+ }
// If it's not an identified object, it might be an argument.
if (!isIdentifiedObject(UO))
@@ -250,7 +265,22 @@ checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR,
if (I.isVolatile())
ME |= MemoryEffects::inaccessibleMemOnly(MR);
+ // Refine memory effects for the given location.
addLocAccess(ME, *Loc, MR, AAR);
+
+ // Last attempt if errnomem has not been inferred yet: accesses larger than
+ // integers cannot alias errno.
+ if (ME.getModRef(IRMemLocation::ErrnoMem) != ModRefInfo::NoModRef) {
+ if (isa<LoadInst>(I) || isa<StoreInst>(I)) {
+ auto *Ty = isa<LoadInst>(I)
+ ? I.getType()
+ : cast<StoreInst>(I).getValueOperand()->getType();
+ if (!Ty->isPtrOrPtrVectorTy() &&
+ Loc->Size != MemoryLocation::UnknownSize &&
+ Loc->Size.getValue() > sizeof(int))
+ ME = ME.getWithoutLoc(IRMemLocation::ErrnoMem);
+ }
+ }
}
return {OrigME & ME, RecursiveArgME};
diff --git a/llvm/test/Transforms/FunctionAttrs/argmemonly.ll b/llvm/test/Transforms/FunctionAttrs/argmemonly.ll
index 42e0e94c1cee3..fe096fcfc43b3 100644
--- a/llvm/test/Transforms/FunctionAttrs/argmemonly.ll
+++ b/llvm/test/Transforms/FunctionAttrs/argmemonly.ll
@@ -334,7 +334,7 @@ define void @test_inaccessiblememonly_readonly() {
; FNATTRS: Function Attrs: nofree memory(inaccessiblemem: read)
; FNATTRS-LABEL: define void @test_inaccessiblememonly_readonly
; FNATTRS-SAME: () #[[ATTR13:[0-9]+]] {
-; FNATTRS-NEXT: call void @fn_inaccessiblememonly() #[[ATTR19:[0-9]+]]
+; FNATTRS-NEXT: call void @fn_inaccessiblememonly() #[[ATTR20:[0-9]+]]
; FNATTRS-NEXT: ret void
;
; ATTRIBUTOR: Function Attrs: nosync memory(inaccessiblemem: read)
@@ -352,7 +352,7 @@ define void @test_inaccessibleorargmemonly_readonly(ptr %arg) {
; FNATTRS-LABEL: define void @test_inaccessibleorargmemonly_readonly
; FNATTRS-SAME: (ptr readonly captures(none) [[ARG:%.*]]) #[[ATTR14:[0-9]+]] {
; FNATTRS-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARG]], align 4
-; FNATTRS-NEXT: call void @fn_inaccessiblememonly() #[[ATTR19]]
+; FNATTRS-NEXT: call void @fn_inaccessiblememonly() #[[ATTR20]]
; FNATTRS-NEXT: ret void
;
; ATTRIBUTOR: Function Attrs: nosync memory(argmem: read, inaccessiblemem: read)
@@ -372,7 +372,7 @@ define void @test_inaccessibleorargmemonly_readwrite(ptr %arg) {
; FNATTRS-LABEL: define void @test_inaccessibleorargmemonly_readwrite
; FNATTRS-SAME: (ptr writeonly captures(none) initializes((0, 4)) [[ARG:%.*]]) #[[ATTR15:[0-9]+]] {
; FNATTRS-NEXT: store i32 0, ptr [[ARG]], align 4
-; FNATTRS-NEXT: call void @fn_inaccessiblememonly() #[[ATTR19]]
+; FNATTRS-NEXT: call void @fn_inaccessiblememonly() #[[ATTR20]]
; FNATTRS-NEXT: ret void
;
; ATTRIBUTOR: Function Attrs: nosync memory(argmem: readwrite, inaccessiblemem: readwrite)
@@ -518,9 +518,9 @@ entry:
; FIXME: This could be `memory(argmem: read)`.
define i64 @select_different_obj(i1 %c, ptr %p, ptr %p2) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, inaccessiblemem: none, errnomem: none)
; FNATTRS-LABEL: define i64 @select_different_obj
-; FNATTRS-SAME: (i1 [[C:%.*]], ptr readonly captures(none) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR3]] {
+; FNATTRS-SAME: (i1 [[C:%.*]], ptr readonly captures(none) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR19:[0-9]+]] {
; FNATTRS-NEXT: entry:
; FNATTRS-NEXT: [[P3:%.*]] = select i1 [[C]], ptr [[P]], ptr [[P2]]
; FNATTRS-NEXT: [[R:%.*]] = load i64, ptr [[P3]], align 4
@@ -580,9 +580,9 @@ join:
; FIXME: This could be `memory(argmem: read)`.
define i64 @phi_different_obj(i1 %c, ptr %p, ptr %p2) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, inaccessiblemem: none, errnomem: none)
; FNATTRS-LABEL: define i64 @phi_different_obj
-; FNATTRS-SAME: (i1 [[C:%.*]], ptr readonly captures(none) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR3]] {
+; FNATTRS-SAME: (i1 [[C:%.*]], ptr readonly captures(none) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR19]] {
; FNATTRS-NEXT: entry:
; FNATTRS-NEXT: br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]
; FNATTRS: if:
diff --git a/llvm/test/Transforms/FunctionAttrs/errnomemnone.ll b/llvm/test/Transforms/FunctionAttrs/errnomemnone.ll
new file mode 100644
index 0000000000000..be965e5f55340
--- /dev/null
+++ b/llvm/test/Transforms/FunctionAttrs/errnomemnone.ll
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals --version 2
+; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=FNATTRS %s
+
+; Stack-allocated memory cannot alias errno.
+define float @cannot_alias_errno(float %f) {
+; FNATTRS: Function Attrs: memory(readwrite, errnomem: none)
+; FNATTRS-LABEL: define float @cannot_alias_errno
+; FNATTRS-SAME: (float [[F:%.*]]) #[[ATTR0:[0-9]+]] {
+ %p = alloca float
+ call void @escape(ptr %p)
+ store float 0.0, ptr %p
+ call float @sinf(float %f)
+ %v = load float, ptr %p
+ ret float %v
+}
+
+; Accesses to memory larger than integer-size cannot alias errno.
+define double @cannot_alias_errno_2(ptr %p, float %f) {
+; FNATTRS: Function Attrs: memory(readwrite, errnomem: none)
+; FNATTRS-LABEL: define double @cannot_alias_errno_2
+; FNATTRS-SAME: (ptr [[P:%.*]], float [[F:%.*]]) #[[ATTR0]] {
+ call void @escape(ptr %p)
+ store double 0.0, ptr %p
+ call float @sinf(float %f)
+ %v = load double, ptr %p
+ ret double %v
+}
+
+declare void @escape(ptr %p)
+declare float @sinf(float) memory(errnomem: write)
diff --git a/llvm/test/Transforms/FunctionAttrs/initializes.ll b/llvm/test/Transforms/FunctionAttrs/initializes.ll
index 861c61d683ae0..b3362589d3f8b 100644
--- a/llvm/test/Transforms/FunctionAttrs/initializes.ll
+++ b/llvm/test/Transforms/FunctionAttrs/initializes.ll
@@ -91,8 +91,9 @@ define void @partial_load_before_store(ptr %p) {
declare void @use(ptr)
define void @call_clobber(ptr %p) {
+; CHECK: Function Attrs: memory(readwrite, errnomem: none)
; CHECK-LABEL: define void @call_clobber(
-; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: call void @use(ptr [[P]])
; CHECK-NEXT: store i64 123, ptr [[P]], align 4
; CHECK-NEXT: ret void
@@ -130,7 +131,7 @@ define void @store_offset(ptr %p) {
define void @store_volatile(ptr %p) {
; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)
; CHECK-LABEL: define void @store_volatile(
-; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR2:[0-9]+]] {
+; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 8
; CHECK-NEXT: store volatile i32 123, ptr [[G]], align 4
; CHECK-NEXT: ret void
@@ -241,8 +242,9 @@ end:
}
define void @call_clobber_on_one_branch(ptr %p, i1 %i) {
+; CHECK: Function Attrs: memory(readwrite, errnomem: none)
; CHECK-LABEL: define void @call_clobber_on_one_branch(
-; CHECK-SAME: ptr [[P:%.*]], i1 [[I:%.*]]) {
+; CHECK-SAME: ptr [[P:%.*]], i1 [[I:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
@@ -306,8 +308,9 @@ define void @non_const_gep(ptr %p, i64 %i) {
}
define void @call_clobber_in_entry_block(ptr %p, i1 %i) {
+; CHECK: Function Attrs: memory(readwrite, errnomem: none)
; CHECK-LABEL: define void @call_clobber_in_entry_block(
-; CHECK-SAME: ptr [[P:%.*]], i1 [[I:%.*]]) {
+; CHECK-SAME: ptr [[P:%.*]], i1 [[I:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @use(ptr [[P]])
; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]
@@ -384,7 +387,7 @@ define void @call_initializes_escape_bundle(ptr %p) {
define void @access_bundle() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define void @access_bundle(
-; CHECK-SAME: ) #[[ATTR3:[0-9]+]] {
+; CHECK-SAME: ) #[[ATTR4:[0-9]+]] {
; CHECK-NEXT: [[SINK:%.*]] = alloca i64, align 8
; CHECK-NEXT: store i64 123, ptr [[SINK]], align 4
; CHECK-NEXT: ret void
@@ -397,7 +400,7 @@ define void @access_bundle() {
define void @call_operand_bundle(ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CHECK-LABEL: define void @call_operand_bundle(
-; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR4:[0-9]+]] {
+; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR5:[0-9]+]] {
; CHECK-NEXT: call void @access_bundle() [ "unknown"(ptr [[P]]) ]
; CHECK-NEXT: ret void
;
@@ -445,7 +448,7 @@ define void @memset_neg(ptr %p) {
define void @memset_volatile(ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: write)
; CHECK-LABEL: define void @memset_volatile(
-; CHECK-SAME: ptr writeonly [[P:%.*]]) #[[ATTR5:[0-9]+]] {
+; CHECK-SAME: ptr writeonly [[P:%.*]]) #[[ATTR6:[0-9]+]] {
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 2, i64 9, i1 true)
; CHECK-NEXT: ret void
;
@@ -480,7 +483,7 @@ 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)
; 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:%.*]]) #[[ATTR7:[0-9]+]] {
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 9, i1 true)
; CHECK-NEXT: ret void
;
@@ -543,7 +546,7 @@ 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)
; CHECK-LABEL: define void @memmove_volatile(
-; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR6]] {
+; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR7]] {
; 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/read-write-errnomem.ll b/llvm/test/Transforms/FunctionAttrs/read-write-errnomem.ll
new file mode 100644
index 0000000000000..db8effc45442f
--- /dev/null
+++ b/llvm/test/Transforms/FunctionAttrs/read-write-errnomem.ll
@@ -0,0 +1,71 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals --version 2
+; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=FNATTRS %s
+; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=ATTRIBUTOR %s
+
+define i32 @test_read_errno() {
+; FNATTRS: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(errnomem: read)
+; FNATTRS-LABEL: define i32 @test_read_errno
+; FNATTRS-SAME: () #[[ATTR0:[0-9]+]] {
+; FNATTRS-NEXT: [[CALL:%.*]] = call ptr @__errno_location() #[[ATTR4:[0-9]+]]
+; FNATTRS-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; FNATTRS-NEXT: ret i32 [[ERRNO]]
+;
+; ATTRIBUTOR: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)
+; ATTRIBUTOR-LABEL: define i32 @test_read_errno
+; ATTRIBUTOR-SAME: () #[[ATTR0:[0-9]+]] {
+; ATTRIBUTOR-NEXT: [[CALL:%.*]] = call ptr @__errno_location() #[[ATTR4:[0-9]+]]
+; ATTRIBUTOR-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT: ret i32 [[ERRNO]]
+;
+ %call = call ptr @__errno_location() #2
+ %errno = load i32, ptr %call
+ ret i32 %errno
+}
+
+define ptr @test_write_errno() {
+; FNATTRS: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(errnomem: write)
+; FNATTRS-LABEL: define noundef ptr @test_write_errno
+; FNATTRS-SAME: () #[[ATTR1:[0-9]+]] {
+; FNATTRS-NEXT: [[CALL:%.*]] = call ptr @__errno_location() #[[ATTR4]]
+; FNATTRS-NEXT: store i32 0, ptr [[CALL]], align 4
+; FNATTRS-NEXT: ret ptr [[CALL]]
+;
+; ATTRIBUTOR: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
+; ATTRIBUTOR-LABEL: define ptr @test_write_errno
+; ATTRIBUTOR-SAME: () #[[ATTR1:[0-9]+]] {
+; ATTRIBUTOR-NEXT: [[CALL:%.*]] = call ptr @__errno_location() #[[ATTR4]]
+; ATTRIBUTOR-NEXT: store i32 0, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT: ret ptr [[CALL]]
+;
+ %call = call ptr @__errno_location() #2
+ store i32 0, ptr %call
+ ret ptr %call
+}
+
+define i32 @test_readwrite_errno() {
+; FNATTRS: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(errnomem: readwrite)
+; FNATTRS-LABEL: define i32 @test_readwrite_errno
+; FNATTRS-SAME: () #[[ATTR2:[0-9]+]] {
+; FNATTRS-NEXT: [[CALL:%.*]] = call ptr @__errno_location() #[[ATTR4]]
+; FNATTRS-NEXT: store i32 0, ptr [[CALL]], align 4
+; FNATTRS-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; FNATTRS-NEXT: ret i32 [[ERRNO]]
+;
+; ATTRIBUTOR: Function Attrs: mustprogress nofree nosync nounwind willreturn
+; ATTRIBUTOR-LABEL: define i32 @test_readwrite_errno
+; ATTRIBUTOR-SAME: () #[[ATTR2:[0-9]+]] {
+; ATTRIBUTOR-NEXT: [[CALL:%.*]] = call ptr @__errno_location() #[[ATTR4]]
+; ATTRIBUTOR-NEXT: store i32 0, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT: ret i32 [[ERRNO]]
+;
+ %call = call ptr @__errno_location() #2
+ store i32 0, ptr %call
+ %errno = load i32, ptr %call
+ ret i32 %errno
+}
+
+declare ptr @__errno_location() #1
+
+attributes #1 = { mustprogress nofree nosync nounwind willreturn memory(none) }
+attributes #2 = { nounwind willreturn memory(none) }
diff --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index b24c097ad54d0..ec6e116837478 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -376,8 +376,9 @@ declare void @escape_readonly_ptr(ptr %addr, ptr readonly %ptr)
; is marked as readnone/only. However, the functions can write the pointer into
; %addr, causing the store to write to %escaped_then_written.
define void @unsound_readnone(ptr %ignored, ptr %escaped_then_written) {
+; FNATTRS: Function Attrs: memory(readwrite, errnomem: write)
; FNATTRS-LABEL: define {{[^@]+}}@unsound_readnone
-; FNATTRS-SAME: (ptr readnone captures(none) [[IGNORED:%.*]], ptr [[ESCAPED_THEN_WRITTEN:%.*]]) {
+; FNATTRS-SAME: (ptr readnone captures(none) [[IGNORED:%.*]], ptr [[ESCAPED_THEN_WRITTEN:%.*]]) #[[ATTR14:[0-9]+]] {
; FNATTRS-NEXT: [[ADDR:%.*]] = alloca ptr, align 8
; FNATTRS-NEXT: call void @escape_readnone_ptr(ptr [[ADDR]], ptr [[ESCAPED_THEN_WRITTEN]])
; FNATTRS-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8
@@ -408,8 +409,9 @@ define void @unsound_readnone(ptr %ignored, ptr %escaped_then_written) {
}
define void @unsound_readonly(ptr %ignored, ptr %escaped_then_written) {
+; FNATTRS: Function Attrs: memory(readwrite, errnomem: write)
; FNATTRS-LABEL: define {{[^@]+}}@unsound_readonly
-; FNATTRS-SAME: (ptr readnone captures(none) [[IGNORED:%.*]], ptr [[ESCAPED_THEN_WRITTEN:%.*]]) {
+; FNATTRS-SAME: (ptr readnone captures(none) [[IGNORED:%.*]], ptr [[ESCAPED_THEN_WRITTEN:%.*]]) #[[ATTR14]] {
; FNATTRS-NEXT: [[ADDR:%.*]] = alloca ptr, align 8
; FNATTRS-NEXT: call void @escape_readonly_ptr(ptr [[ADDR]], ptr [[ESCAPED_THEN_WRITTEN]])
; FNATTRS-NEXT: [[ADDR_LD:%.*]] = load ptr, ptr [[ADDR]], align 8
@@ -570,7 +572,7 @@ define void @fptr_test2c(ptr %p, ptr %f) {
define void @alloca_recphi() {
; FNATTRS: Function Attrs: nofree norecurse nosync nounwind memory(none)
; FNATTRS-LABEL: define {{[^@]+}}@alloca_recphi
-; FNATTRS-SAME: () #[[ATTR14:[0-9]+]] {
+; FNATTRS-SAME: () #[[ATTR15:[0-9]+]] {
; FNATTRS-NEXT: entry:
; FNATTRS-NEXT: [[A:%.*]] = alloca [8 x i32], align 4
; FNATTRS-NEXT: [[A_END:%.*]] = getelementptr i32, ptr [[A]], i64 8
@@ -723,7 +725,7 @@ define void @op_bundle_readonly_unknown(ptr %p) {
define i32 @writable_readonly(ptr writable dereferenceable(4) %p) {
; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; FNATTRS-LABEL: define {{[^@]+}}@writable_readonly
-; FNATTRS-SAME: (ptr readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR15:[0-9]+]] {
+; FNATTRS-SAME: (ptr readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR16:[0-9]+]] {
; FNATTRS-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 4
; FNATTRS-NEXT: ret i32 [[V]]
;
diff --git a/llvm/test/Transforms/PhaseOrdering/pr95152.ll b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
index 1e28856f32bd4..9c9ebd2dff3f5 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr95152.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
@@ -45,7 +45,7 @@ define void @g(ptr dead_on_unwind noalias writable dereferenceable(8) align 8 %p
define void @f(ptr dead_on_unwind noalias %p) {
; CHECK-LABEL: define void @f(
-; CHECK-SAME: ptr dead_on_unwind noalias initializes((0, 8)) [[P:%.*]]) local_unnamed_addr {
+; CHECK-SAME: ptr dead_on_unwind noalias initializes((0, 8)) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: store i64 3, ptr [[P]], align 4
; CHECK-NEXT: tail call void @j(ptr nonnull align 8 dereferenceable(8) [[P]])
; CHECK-NEXT: store i64 43, ptr [[P]], align 4
``````````
</details>
https://github.com/llvm/llvm-project/pull/129067
More information about the llvm-commits
mailing list