[llvm] [Attributor] Avoid inferring align and nonnull from poison-producing calls (PR #224932)

via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 20 07:16:04 PDT 2026


https://github.com/xxxxbc updated https://github.com/llvm/llvm-project/pull/224932

>From bf0bf484b35ed96281fb6117465de72d7ea5e873 Mon Sep 17 00:00:00 2001
From: hehuan <2128534713 at qq.com>
Date: Sun, 20 Sep 2026 22:08:07 +0800
Subject: [PATCH] [Attributor] Avoid inferring align and nonnull from
 poison-producing calls

The align and nonnull parameter attributes produce poison when their
constraints are violated. Attributor treated these attributes as facts about
the original caller value even when the call boundary allowed poison. This
could incorrectly strengthen caller parameters and the alignment of memory
accesses.

Only use align or nonnull attributes from a call site or callee declaration to
reason about the original argument when CallBase::isPassingUndefUB() indicates
that the call rejects poison. Preserve the existing positive propagation tests
by adding noundef, and add regression coverage for both attributes with and
without noundef in module and CGSCC modes.

Fixes #224817
---
 .../Transforms/IPO/AttributorAttributes.cpp   |  25 +++-
 .../X86/min-legal-vector-width.ll             |  16 +--
 llvm/test/Transforms/Attributor/align.ll      |  16 +--
 .../Attributor/call-site-argument-poison.ll   |  51 ++++++++
 llvm/test/Transforms/Attributor/callbacks.ll  |  50 +++----
 llvm/test/Transforms/Attributor/nonnull.ll    | 122 +++++++++---------
 6 files changed, 172 insertions(+), 108 deletions(-)
 create mode 100644 llvm/test/Transforms/Attributor/call-site-argument-poison.ll

diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 04b7d34b02fb2..5d8e27e5701d6 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -2542,12 +2542,18 @@ static int64_t getKnownNonNullAndDerefBytesForUse(
 
     unsigned ArgNo = CB->getArgOperandNo(U);
     IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
-    // As long as we only use known information there is no need to track
-    // dependences here.
-    bool IsKnownNonNull;
-    AA::hasAssumedIRAttr<Attribute::NonNull>(A, &QueryingAA, IRP,
-                                             DepClassTy::NONE, IsKnownNonNull);
-    IsNonNull |= IsKnownNonNull;
+    // The nonnull attribute produces poison if its constraint is violated. It
+    // therefore only proves that the original value is nonnull if poison is
+    // not accepted at this call boundary.
+    if (!CB->paramHasAttr(ArgNo, Attribute::NonNull) ||
+        CB->isPassingUndefUB(ArgNo)) {
+      // As long as we only use known information there is no need to track
+      // dependences here.
+      bool IsKnownNonNull;
+      AA::hasAssumedIRAttr<Attribute::NonNull>(
+          A, &QueryingAA, IRP, DepClassTy::NONE, IsKnownNonNull);
+      IsNonNull |= IsKnownNonNull;
+    }
     auto *DerefAA =
         A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
     return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
@@ -5295,6 +5301,13 @@ static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
       return 0;
 
     unsigned ArgNo = CB->getArgOperandNo(U);
+    // The align attribute produces poison if its constraint is violated. It
+    // therefore only proves that the original value is aligned if poison is
+    // not accepted at this call boundary.
+    if (CB->paramHasAttr(ArgNo, Attribute::Alignment) &&
+        !CB->isPassingUndefUB(ArgNo))
+      return 0;
+
     IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
     // As long as we only use known information there is no need to track
     // dependences here.
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 d7a9c6748d905..d38338a010f72 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
@@ -66,7 +66,7 @@ define void @avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr %arg)
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
@@ -133,7 +133,7 @@ define void @avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr %arg)
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
@@ -200,7 +200,7 @@ define void @avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr %arg)
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
@@ -267,7 +267,7 @@ define void @avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr %arg)
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
@@ -328,7 +328,7 @@ define void @avx512_legal256_prefer256_call_avx512_legal512_prefer256(ptr %arg)
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
@@ -389,7 +389,7 @@ define void @avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr %arg)
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
@@ -456,7 +456,7 @@ define void @avx2_legal256_prefer256_call_avx2_legal512_prefer256(ptr %arg) #4 {
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
@@ -523,7 +523,7 @@ define void @avx2_legal512_prefer256_call_avx2_legal256_prefer256(ptr %arg) #3 {
 bb:
   %tmp = alloca <8 x i64>, align 32
   %tmp2 = alloca <8 x i64>, align 32
-  call void @llvm.memset.p0.i64(ptr align 32 %tmp, i8 0, i64 32, i1 false)
+  call void @llvm.memset.p0.i64(ptr noundef align 32 %tmp, i8 0, i64 32, i1 false)
   call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(ptr %tmp2, ptr %tmp)
   %tmp4 = load <8 x i64>, ptr %tmp2, align 32
   store <8 x i64> %tmp4, ptr %arg, align 2
diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll
index 904233408c144..6de922da0cf48 100644
--- a/llvm/test/Transforms/Attributor/align.ll
+++ b/llvm/test/Transforms/Attributor/align.ll
@@ -649,7 +649,7 @@ define void @test12-5(ptr align 4 %p) {
 ; TUNIT-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR7:[0-9]+]] {
 ; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
 ; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
-; TUNIT-NEXT:    tail call void @use(ptr align 16 [[ARRAYIDX1]]) #[[ATTR6:[0-9]+]]
+; TUNIT-NEXT:    tail call void @use(ptr noundef align 16 [[ARRAYIDX1]]) #[[ATTR6:[0-9]+]]
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: mustprogress nounwind willreturn
@@ -657,13 +657,13 @@ define void @test12-5(ptr align 4 %p) {
 ; CGSCC-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR8:[0-9]+]] {
 ; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
 ; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
-; CGSCC-NEXT:    tail call void @use(ptr align 16 [[ARRAYIDX1]]) #[[ATTR7:[0-9]+]]
+; CGSCC-NEXT:    tail call void @use(ptr noundef align 16 [[ARRAYIDX1]]) #[[ATTR7:[0-9]+]]
 ; CGSCC-NEXT:    ret void
 ;
   %p-cast = bitcast ptr %p to ptr
   %arrayidx0 = getelementptr i64, ptr %p-cast, i64 1
   %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
-  tail call void @use(ptr align 16 %arrayidx1)
+  tail call void @use(ptr noundef align 16 %arrayidx1)
   ret void
 }
 
@@ -671,17 +671,17 @@ define void @test12-6(ptr align 4 %p) {
 ; TUNIT: Function Attrs: mustprogress nounwind willreturn
 ; TUNIT-LABEL: define {{[^@]+}}@test12-6
 ; TUNIT-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR7]] {
-; TUNIT-NEXT:    tail call void @use(ptr align 16 [[P]]) #[[ATTR6]]
+; TUNIT-NEXT:    tail call void @use(ptr noundef align 16 [[P]]) #[[ATTR6]]
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: mustprogress nounwind willreturn
 ; CGSCC-LABEL: define {{[^@]+}}@test12-6
 ; CGSCC-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR8]] {
-; CGSCC-NEXT:    tail call void @use(ptr align 16 [[P]]) #[[ATTR7]]
+; CGSCC-NEXT:    tail call void @use(ptr noundef align 16 [[P]]) #[[ATTR7]]
 ; CGSCC-NEXT:    ret void
 ;
   %p-cast = bitcast ptr %p to ptr
-  tail call void @use(ptr align 16 %p-cast)
+  tail call void @use(ptr noundef align 16 %p-cast)
   ret void
 }
 
@@ -1020,10 +1020,10 @@ return:                                           ; preds = %entry, %if.then
   ret ptr %retval.0
 }
 
-; FIXME: align 4 should not be propagated to the caller's p unless there is noundef
+; The align attribute does not describe the caller's value without noundef.
 define void @align4_caller(ptr %p) {
 ; CHECK-LABEL: define {{[^@]+}}@align4_caller
-; CHECK-SAME: (ptr align 4 [[P:%.*]]) {
+; CHECK-SAME: (ptr [[P:%.*]]) {
 ; CHECK-NEXT:    call void @align4_callee(ptr align 4 [[P]])
 ; CHECK-NEXT:    ret void
 ;
diff --git a/llvm/test/Transforms/Attributor/call-site-argument-poison.ll b/llvm/test/Transforms/Attributor/call-site-argument-poison.ll
new file mode 100644
index 0000000000000..d79389114dbf2
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/call-site-argument-poison.ll
@@ -0,0 +1,51 @@
+; RUN: opt -passes=attributor -S < %s | FileCheck %s
+; RUN: opt -passes=attributor-cgscc -S < %s | FileCheck %s
+
+declare void @use(ptr)
+
+; Parameter attributes such as align and nonnull produce poison when their
+; constraints are violated. Unless the argument is also noundef (or otherwise
+; rejects poison), these attributes do not describe the original value.
+
+define void @align_without_noundef(ptr %p) {
+; CHECK-LABEL: define void @align_without_noundef(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @use(ptr align 4 [[P]])
+; CHECK-NEXT:    store i8 1, ptr [[P]], align 1
+; CHECK-NEXT:    ret void
+  call void @use(ptr align 4 %p)
+  store i8 1, ptr %p, align 1
+  ret void
+}
+
+define void @align_with_noundef(ptr %p) {
+; CHECK-LABEL: define void @align_with_noundef(
+; CHECK-SAME: ptr noundef align 4 [[P:%.*]]) {
+; CHECK-NEXT:    call void @use(ptr noundef align 4 [[P]])
+; CHECK-NEXT:    store i8 1, ptr [[P]], align 4
+; CHECK-NEXT:    ret void
+  call void @use(ptr noundef align 4 %p)
+  store i8 1, ptr %p, align 1
+  ret void
+}
+
+define i1 @nonnull_without_noundef(ptr %p) {
+; CHECK-LABEL: define i1 @nonnull_without_noundef(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @use(ptr nonnull [[P]])
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne ptr [[P]], null
+; CHECK-NEXT:    ret i1 [[CMP]]
+  call void @use(ptr nonnull %p)
+  %cmp = icmp ne ptr %p, null
+  ret i1 %cmp
+}
+
+define i1 @nonnull_with_noundef(ptr %p) {
+; CHECK-LABEL: define noundef i1 @nonnull_with_noundef(
+; CHECK-SAME: ptr noundef nonnull [[P:%.*]]) {
+; CHECK-NEXT:    call void @use(ptr noundef nonnull [[P]])
+; CHECK-NEXT:    ret i1 true
+  call void @use(ptr noundef nonnull %p)
+  %cmp = icmp ne ptr %p, null
+  ret i1 %cmp
+}
diff --git a/llvm/test/Transforms/Attributor/callbacks.ll b/llvm/test/Transforms/Attributor/callbacks.ll
index 80a0b2befbbee..601dadc281f88 100644
--- a/llvm/test/Transforms/Attributor/callbacks.ll
+++ b/llvm/test/Transforms/Attributor/callbacks.ll
@@ -33,7 +33,7 @@ define void @t0_caller(ptr %a) {
 ; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 128
 ; CGSCC-NEXT:    store i32 42, ptr [[B]], align 32
 ; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 64
-; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr noundef null, ptr noundef nonnull align 128 dereferenceable(4) [[PTR]], ptr noundef nonnull @t0_callback_callee, ptr align 256 [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
+; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr noundef null, ptr noundef nonnull align 128 dereferenceable(4) [[PTR]], ptr noundef nonnull @t0_callback_callee, ptr noundef align 256 [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -51,21 +51,21 @@ entry:
 define internal void @t0_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64 %b, ptr %c) {
 ;
 ; TUNIT-LABEL: define {{[^@]+}}@t0_callback_callee
-; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
+; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
 ; TUNIT-NEXT:  entry:
 ; TUNIT-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; TUNIT-NEXT:    tail call void @t0_check(ptr align 256 [[A]], i64 noundef 99, ptr align 32 [[TMP0]])
+; TUNIT-NEXT:    tail call void @t0_check(ptr noundef align 256 [[A]], i64 noundef 99, ptr align 32 [[TMP0]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@t0_callback_callee
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; CGSCC-NEXT:    tail call void @t0_check(ptr align 256 [[A]], i64 noundef 99, ptr [[TMP0]])
+; CGSCC-NEXT:    tail call void @t0_check(ptr noundef align 256 [[A]], i64 noundef 99, ptr [[TMP0]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -76,7 +76,7 @@ entry:
   ret void
 }
 
-declare void @t0_check(ptr align 256, i64, ptr)
+declare void @t0_check(ptr noundef align 256, i64, ptr)
 
 declare !callback !0 void @t0_callback_broker(ptr, ptr, ptr, ...)
 
@@ -106,7 +106,7 @@ define void @t1_caller(ptr noalias %a) {
 ; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 128
 ; CGSCC-NEXT:    store i32 42, ptr [[B]], align 32
 ; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 64
-; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t1_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
+; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t1_callback_callee, ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -125,22 +125,22 @@ define internal void @t1_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64
 ;
 ; TUNIT: Function Attrs: nosync
 ; TUNIT-LABEL: define {{[^@]+}}@t1_callback_callee
-; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] {
+; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] {
 ; TUNIT-NEXT:  entry:
 ; TUNIT-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; TUNIT-NEXT:    tail call void @t1_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]])
+; TUNIT-NEXT:    tail call void @t1_check(ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: nosync
 ; CGSCC-LABEL: define {{[^@]+}}@t1_callback_callee
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; CGSCC-NEXT:    tail call void @t1_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])
+; CGSCC-NEXT:    tail call void @t1_check(ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -151,7 +151,7 @@ entry:
   ret void
 }
 
-declare void @t1_check(ptr nocapture align 256, i64, ptr nocapture) nosync
+declare void @t1_check(ptr nocapture noundef align 256, i64, ptr nocapture) nosync
 
 declare !callback !0 void @t1_callback_broker(ptr nocapture , ptr nocapture , ptr nocapture, ...)
 
@@ -179,7 +179,7 @@ define void @t2_caller(ptr noalias %a) {
 ; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 128
 ; CGSCC-NEXT:    store i32 42, ptr [[B]], align 32
 ; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 64
-; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t2_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
+; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t2_callback_callee, ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -199,21 +199,21 @@ entry:
 define internal void @t2_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64 %b, ptr %c) {
 ;
 ; TUNIT-LABEL: define {{[^@]+}}@t2_callback_callee
-; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
+; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
 ; TUNIT-NEXT:  entry:
 ; TUNIT-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; TUNIT-NEXT:    tail call void @t2_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]])
+; TUNIT-NEXT:    tail call void @t2_check(ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@t2_callback_callee
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; CGSCC-NEXT:    tail call void @t2_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])
+; CGSCC-NEXT:    tail call void @t2_check(ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -224,7 +224,7 @@ entry:
   ret void
 }
 
-declare void @t2_check(ptr nocapture align 256, i64, ptr nocapture)
+declare void @t2_check(ptr nocapture noundef align 256, i64, ptr nocapture)
 
 declare !callback !0 void @t2_callback_broker(ptr nocapture , ptr nocapture , ptr nocapture, ...)
 
@@ -253,8 +253,8 @@ define void @t3_caller(ptr noalias %a) {
 ; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 128
 ; CGSCC-NEXT:    store i32 42, ptr [[B]], align 32
 ; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 64
-; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
-; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
+; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
+; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -275,21 +275,21 @@ entry:
 define internal void @t3_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64 %b, ptr %c) {
 ;
 ; TUNIT-LABEL: define {{[^@]+}}@t3_callback_callee
-; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
+; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
 ; TUNIT-NEXT:  entry:
 ; TUNIT-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; TUNIT-NEXT:    tail call void @t3_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]])
+; TUNIT-NEXT:    tail call void @t3_check(ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@t3_callback_callee
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr noundef align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8
 ; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64
-; CGSCC-NEXT:    tail call void @t3_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])
+; CGSCC-NEXT:    tail call void @t3_check(ptr noundef align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -300,7 +300,7 @@ entry:
   ret void
 }
 
-declare void @t3_check(ptr nocapture align 256, i64, ptr nocapture)
+declare void @t3_check(ptr nocapture noundef align 256, i64, ptr nocapture)
 
 declare !callback !0 void @t3_callback_broker(ptr nocapture , ptr nocapture , ptr nocapture, ...)
 
diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll
index 0aa0e72d403ab..e7a81a88383b3 100644
--- a/llvm/test/Transforms/Attributor/nonnull.ll
+++ b/llvm/test/Transforms/Attributor/nonnull.ll
@@ -533,10 +533,10 @@ define void @f16(ptr %a, ptr %b, i8 %c) {
 ; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0
 ; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
 ; TUNIT:       if.then:
-; TUNIT-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR7:[0-9]+]]
+; TUNIT-NEXT:    tail call void @fun2(ptr noundef nonnull [[A]], ptr noundef nonnull [[B]]) #[[ATTR7:[0-9]+]]
 ; TUNIT-NEXT:    ret void
 ; TUNIT:       if.else:
-; TUNIT-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR7]]
+; TUNIT-NEXT:    tail call void @fun2(ptr noundef nonnull [[A]], ptr [[B]]) #[[ATTR7]]
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: mustprogress nounwind willreturn
@@ -545,19 +545,19 @@ define void @f16(ptr %a, ptr %b, i8 %c) {
 ; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0
 ; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
 ; CGSCC:       if.then:
-; CGSCC-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR6:[0-9]+]]
+; CGSCC-NEXT:    tail call void @fun2(ptr noundef nonnull [[A]], ptr noundef nonnull [[B]]) #[[ATTR6:[0-9]+]]
 ; CGSCC-NEXT:    ret void
 ; CGSCC:       if.else:
-; CGSCC-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR6]]
+; CGSCC-NEXT:    tail call void @fun2(ptr noundef nonnull [[A]], ptr [[B]]) #[[ATTR6]]
 ; CGSCC-NEXT:    ret void
 ;
   %cmp = icmp eq i8 %c, 0
   br i1 %cmp, label %if.then, label %if.else
 if.then:
-  tail call void @fun2(ptr nonnull %a, ptr nonnull %b)
+  tail call void @fun2(ptr noundef nonnull %a, ptr noundef nonnull %b)
   ret void
 if.else:
-  tail call void @fun2(ptr nonnull %a, ptr %b)
+  tail call void @fun2(ptr noundef nonnull %a, ptr %b)
   ret void
 }
 ; TEST 17 explore child BB test
@@ -581,7 +581,7 @@ define void @f17(ptr %a, i8 %c) {
 ; TUNIT-NEXT:    tail call void @fun0() #[[ATTR7]]
 ; TUNIT-NEXT:    br label [[CONT]]
 ; TUNIT:       cont:
-; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR7]]
+; TUNIT-NEXT:    tail call void @fun1(ptr noundef nonnull [[A]]) #[[ATTR7]]
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: mustprogress nounwind willreturn
@@ -596,7 +596,7 @@ define void @f17(ptr %a, i8 %c) {
 ; CGSCC-NEXT:    tail call void @fun0() #[[ATTR6]]
 ; CGSCC-NEXT:    br label [[CONT]]
 ; CGSCC:       cont:
-; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR6]]
+; CGSCC-NEXT:    tail call void @fun1(ptr noundef nonnull [[A]]) #[[ATTR6]]
 ; CGSCC-NEXT:    ret void
 ;
   %cmp = icmp eq i8 %c, 0
@@ -608,7 +608,7 @@ if.else:
   tail call void @fun0()
   br label %cont
 cont:
-  tail call void @fun1(ptr nonnull %a)
+  tail call void @fun1(ptr noundef nonnull %a)
   ret void
 }
 ; TEST 18 More complex test
@@ -638,13 +638,13 @@ define void @f18(ptr %a, ptr %b, i8 %c) {
 ; TUNIT-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 1
 ; TUNIT-NEXT:    br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]
 ; TUNIT:       cont.then:
-; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR7]]
+; TUNIT-NEXT:    tail call void @fun1(ptr noundef nonnull [[B]]) #[[ATTR7]]
 ; TUNIT-NEXT:    br label [[CONT2:%.*]]
 ; TUNIT:       cont.else:
 ; TUNIT-NEXT:    tail call void @fun0() #[[ATTR7]]
 ; TUNIT-NEXT:    br label [[CONT2]]
 ; TUNIT:       cont2:
-; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR7]]
+; TUNIT-NEXT:    tail call void @fun1(ptr noundef nonnull [[A]]) #[[ATTR7]]
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: mustprogress nounwind willreturn
@@ -662,13 +662,13 @@ define void @f18(ptr %a, ptr %b, i8 %c) {
 ; CGSCC-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 1
 ; CGSCC-NEXT:    br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]
 ; CGSCC:       cont.then:
-; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR6]]
+; CGSCC-NEXT:    tail call void @fun1(ptr noundef nonnull [[B]]) #[[ATTR6]]
 ; CGSCC-NEXT:    br label [[CONT2:%.*]]
 ; CGSCC:       cont.else:
 ; CGSCC-NEXT:    tail call void @fun0() #[[ATTR6]]
 ; CGSCC-NEXT:    br label [[CONT2]]
 ; CGSCC:       cont2:
-; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR6]]
+; CGSCC-NEXT:    tail call void @fun1(ptr noundef nonnull [[A]]) #[[ATTR6]]
 ; CGSCC-NEXT:    ret void
 ;
   %cmp1 = icmp eq i8 %c, 0
@@ -683,13 +683,13 @@ cont:
   %cmp2 = icmp eq i8 %c, 1
   br i1 %cmp2, label %cont.then, label %cont.else
 cont.then:
-  tail call void @fun1(ptr nonnull %b)
+  tail call void @fun1(ptr noundef nonnull %b)
   br label %cont2
 cont.else:
   tail call void @fun0()
   br label %cont2
 cont2:
-  tail call void @fun1(ptr nonnull %a)
+  tail call void @fun1(ptr noundef nonnull %a)
   ret void
 }
 
@@ -704,11 +704,11 @@ define void @f19(ptr %a, ptr %b, i8 %c) {
 ; TUNIT-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 0
 ; TUNIT-NEXT:    br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]
 ; TUNIT:       loop.body:
-; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR5]]
-; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR5]]
+; TUNIT-NEXT:    tail call void @fun1(ptr noundef nonnull [[B]]) #[[ATTR5]]
+; TUNIT-NEXT:    tail call void @fun1(ptr noundef nonnull [[A]]) #[[ATTR5]]
 ; TUNIT-NEXT:    br label [[LOOP_HEADER]]
 ; TUNIT:       loop.exit:
-; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR5]]
+; TUNIT-NEXT:    tail call void @fun1(ptr noundef nonnull [[B]]) #[[ATTR5]]
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: nounwind
@@ -719,11 +719,11 @@ define void @f19(ptr %a, ptr %b, i8 %c) {
 ; CGSCC-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 0
 ; CGSCC-NEXT:    br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]
 ; CGSCC:       loop.body:
-; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR4]]
-; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR4]]
+; CGSCC-NEXT:    tail call void @fun1(ptr noundef nonnull [[B]]) #[[ATTR4]]
+; CGSCC-NEXT:    tail call void @fun1(ptr noundef nonnull [[A]]) #[[ATTR4]]
 ; CGSCC-NEXT:    br label [[LOOP_HEADER]]
 ; CGSCC:       loop.exit:
-; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR4]]
+; CGSCC-NEXT:    tail call void @fun1(ptr noundef nonnull [[B]]) #[[ATTR4]]
 ; CGSCC-NEXT:    ret void
 ;
   br label %loop.header
@@ -731,11 +731,11 @@ loop.header:
   %cmp2 = icmp eq i8 %c, 0
   br i1 %cmp2, label %loop.body, label %loop.exit
 loop.body:
-  tail call void @fun1(ptr nonnull %b)
-  tail call void @fun1(ptr nonnull %a)
+  tail call void @fun1(ptr noundef nonnull %b)
+  tail call void @fun1(ptr noundef nonnull %a)
   br label %loop.header
 loop.exit:
-  tail call void @fun1(ptr nonnull %b)
+  tail call void @fun1(ptr noundef nonnull %b)
   ret void
 }
 
@@ -745,9 +745,9 @@ declare void @use1(ptr %x)
 declare void @use2(ptr %x, ptr %y);
 declare void @use3(ptr %x, ptr %y, ptr %z);
 
-declare void @use1nonnull(ptr nonnull %x);
-declare void @use2nonnull(ptr nonnull %x, ptr nonnull %y);
-declare void @use3nonnull(ptr nonnull %x, ptr nonnull %y, ptr nonnull %z);
+declare void @use1nonnull(ptr noundef nonnull %x);
+declare void @use2nonnull(ptr noundef nonnull %x, ptr noundef nonnull %y);
+declare void @use3nonnull(ptr noundef nonnull %x, ptr noundef nonnull %y, ptr noundef nonnull %z);
 
 declare i8 @use1safecall(ptr %x) readonly nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor
 
@@ -757,7 +757,7 @@ define void @parent1(ptr %a, ptr %b, ptr %c) {
 ; CHECK-LABEL: define {{[^@]+}}@parent1
 ; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {
 ; CHECK-NEXT:    call void @use3(ptr [[C]], ptr [[A]], ptr [[B]])
-; CHECK-NEXT:    call void @use3nonnull(ptr nonnull [[B]], ptr nonnull [[C]], ptr nonnull [[A]])
+; CHECK-NEXT:    call void @use3nonnull(ptr noundef nonnull [[B]], ptr noundef nonnull [[C]], ptr noundef nonnull [[A]])
 ; CHECK-NEXT:    ret void
 ;
   call void @use3(ptr %c, ptr %a, ptr %b)
@@ -769,9 +769,9 @@ define void @parent1(ptr %a, ptr %b, ptr %c) {
 
 define void @parent2(ptr %a, ptr %b, ptr %c) {
 ; CHECK-LABEL: define {{[^@]+}}@parent2
-; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {
-; CHECK-NEXT:    call void @use3nonnull(ptr nonnull [[B]], ptr nonnull [[C]], ptr nonnull [[A]])
-; CHECK-NEXT:    call void @use3(ptr nonnull [[C]], ptr nonnull [[A]], ptr nonnull [[B]])
+; CHECK-SAME: (ptr noundef nonnull [[A:%.*]], ptr noundef nonnull [[B:%.*]], ptr noundef nonnull [[C:%.*]]) {
+; CHECK-NEXT:    call void @use3nonnull(ptr noundef nonnull [[B]], ptr noundef nonnull [[C]], ptr noundef nonnull [[A]])
+; CHECK-NEXT:    call void @use3(ptr noundef nonnull [[C]], ptr noundef nonnull [[A]], ptr noundef nonnull [[B]])
 ; CHECK-NEXT:    ret void
 ;
 
@@ -784,9 +784,9 @@ define void @parent2(ptr %a, ptr %b, ptr %c) {
 
 define void @parent3(ptr %a, ptr %b, ptr %c) {
 ; CHECK-LABEL: define {{[^@]+}}@parent3
-; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {
-; CHECK-NEXT:    call void @use1nonnull(ptr nonnull [[A]])
-; CHECK-NEXT:    call void @use3(ptr [[C]], ptr [[B]], ptr nonnull [[A]])
+; CHECK-SAME: (ptr noundef nonnull [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {
+; CHECK-NEXT:    call void @use1nonnull(ptr noundef nonnull [[A]])
+; CHECK-NEXT:    call void @use3(ptr [[C]], ptr [[B]], ptr noundef nonnull [[A]])
 ; CHECK-NEXT:    ret void
 ;
 
@@ -800,10 +800,10 @@ define void @parent3(ptr %a, ptr %b, ptr %c) {
 
 define void @parent4(ptr %a, ptr %b, ptr %c) {
 ; CHECK-LABEL: define {{[^@]+}}@parent4
-; CHECK-SAME: (ptr [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {
-; CHECK-NEXT:    call void @use2nonnull(ptr nonnull [[C]], ptr nonnull [[B]])
-; CHECK-NEXT:    call void @use2(ptr [[A]], ptr nonnull [[C]])
-; CHECK-NEXT:    call void @use1(ptr nonnull [[B]])
+; CHECK-SAME: (ptr [[A:%.*]], ptr noundef nonnull [[B:%.*]], ptr noundef nonnull [[C:%.*]]) {
+; CHECK-NEXT:    call void @use2nonnull(ptr noundef nonnull [[C]], ptr noundef nonnull [[B]])
+; CHECK-NEXT:    call void @use2(ptr [[A]], ptr noundef nonnull [[C]])
+; CHECK-NEXT:    call void @use1(ptr noundef nonnull [[B]])
 ; CHECK-NEXT:    ret void
 ;
 
@@ -824,7 +824,7 @@ define void @parent5(ptr %a, i1 %a_is_notnull) {
 ; CHECK-SAME: (ptr [[A:%.*]], i1 noundef [[A_IS_NOTNULL:%.*]]) {
 ; CHECK-NEXT:    br i1 [[A_IS_NOTNULL]], label [[T:%.*]], label [[F:%.*]]
 ; CHECK:       t:
-; CHECK-NEXT:    call void @use1nonnull(ptr nonnull [[A]])
+; CHECK-NEXT:    call void @use1nonnull(ptr noundef nonnull [[A]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       f:
 ; CHECK-NEXT:    ret void
@@ -845,7 +845,7 @@ define i8 @parent6(ptr %a, ptr %b) {
 ; CHECK-LABEL: define {{[^@]+}}@parent6
 ; 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:    call void @use1nonnull(ptr noundef nonnull [[A]])
 ; CHECK-NEXT:    ret i8 [[C]]
 ;
 
@@ -858,9 +858,9 @@ define i8 @parent6(ptr %a, ptr %b) {
 
 define i8 @parent7(ptr %a) {
 ; CHECK-LABEL: define {{[^@]+}}@parent7
-; CHECK-SAME: (ptr nonnull [[A:%.*]]) {
-; CHECK-NEXT:    [[RET:%.*]] = call i8 @use1safecall(ptr nonnull readonly [[A]]) #[[ATTR18:[0-9]+]]
-; CHECK-NEXT:    call void @use1nonnull(ptr nonnull [[A]])
+; CHECK-SAME: (ptr noundef nonnull [[A:%.*]]) {
+; CHECK-NEXT:    [[RET:%.*]] = call i8 @use1safecall(ptr noundef nonnull readonly [[A]]) #[[ATTR18:[0-9]+]]
+; CHECK-NEXT:    call void @use1nonnull(ptr noundef nonnull [[A]])
 ; CHECK-NEXT:    ret i8 [[RET]]
 ;
 
@@ -877,9 +877,9 @@ declare i32 @esfp(...)
 define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{
 ; TUNIT: Function Attrs: nounwind
 ; TUNIT-LABEL: define {{[^@]+}}@parent8
-; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR5]] personality ptr @esfp {
+; TUNIT-SAME: (ptr noundef nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr noundef nonnull [[B:%.*]]) #[[ATTR5]] personality ptr @esfp {
 ; TUNIT-NEXT:  entry:
-; TUNIT-NEXT:    invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])
+; TUNIT-NEXT:    invoke void @use2nonnull(ptr noundef nonnull [[A]], ptr noundef nonnull [[B]])
 ; TUNIT-NEXT:            to label [[CONT:%.*]] unwind label [[EXC:%.*]]
 ; TUNIT:       cont:
 ; TUNIT-NEXT:    ret i1 false
@@ -890,9 +890,9 @@ define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{
 ;
 ; CGSCC: Function Attrs: nounwind
 ; CGSCC-LABEL: define {{[^@]+}}@parent8
-; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR4]] personality ptr @esfp {
+; CGSCC-SAME: (ptr noundef nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr noundef nonnull [[B:%.*]]) #[[ATTR4]] personality ptr @esfp {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])
+; CGSCC-NEXT:    invoke void @use2nonnull(ptr noundef nonnull [[A]], ptr noundef nonnull [[B]])
 ; CGSCC-NEXT:            to label [[CONT:%.*]] unwind label [[EXC:%.*]]
 ; CGSCC:       cont:
 ; CGSCC-NEXT:    ret i1 false
@@ -1103,7 +1103,7 @@ define i32 @nonnull_exec_ctx_1(ptr %a, i32 %b) {
 ; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; TUNIT:       ex:
-; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]]
+; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR7]]
 ; TUNIT-NEXT:    ret i32 [[TMP5]]
 ; TUNIT:       hd:
 ; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
@@ -1119,7 +1119,7 @@ define i32 @nonnull_exec_ctx_1(ptr %a, i32 %b) {
 ; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; CGSCC:       ex:
-; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]]
+; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR6]]
 ; CGSCC-NEXT:    ret i32 [[TMP5]]
 ; CGSCC:       hd:
 ; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
@@ -1133,7 +1133,7 @@ en:
   br i1 %tmp3, label %ex, label %hd
 
 ex:
-  %tmp5 = tail call i32 @g(ptr nonnull %a)
+  %tmp5 = tail call i32 @g(ptr noundef nonnull %a)
   ret i32 %tmp5
 
 hd:
@@ -1153,7 +1153,7 @@ define i32 @nonnull_exec_ctx_1b(ptr %a, i32 %b) {
 ; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; TUNIT:       ex:
-; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]]
+; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR7]]
 ; TUNIT-NEXT:    ret i32 [[TMP5]]
 ; TUNIT:       hd:
 ; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
@@ -1171,7 +1171,7 @@ define i32 @nonnull_exec_ctx_1b(ptr %a, i32 %b) {
 ; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; CGSCC:       ex:
-; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]]
+; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR6]]
 ; CGSCC-NEXT:    ret i32 [[TMP5]]
 ; CGSCC:       hd:
 ; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
@@ -1187,7 +1187,7 @@ en:
   br i1 %tmp3, label %ex, label %hd
 
 ex:
-  %tmp5 = tail call i32 @g(ptr nonnull %a)
+  %tmp5 = tail call i32 @g(ptr noundef nonnull %a)
   ret i32 %tmp5
 
 hd:
@@ -1210,7 +1210,7 @@ define i32 @nonnull_exec_ctx_2(ptr %a, i32 %b) willreturn nounwind {
 ; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; TUNIT:       ex:
-; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]]
+; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR5]]
 ; TUNIT-NEXT:    ret i32 [[TMP5]]
 ; TUNIT:       hd:
 ; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
@@ -1226,7 +1226,7 @@ define i32 @nonnull_exec_ctx_2(ptr %a, i32 %b) willreturn nounwind {
 ; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; CGSCC:       ex:
-; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]]
+; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR4]]
 ; CGSCC-NEXT:    ret i32 [[TMP5]]
 ; CGSCC:       hd:
 ; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
@@ -1240,7 +1240,7 @@ en:
   br i1 %tmp3, label %ex, label %hd
 
 ex:
-  %tmp5 = tail call i32 @g(ptr nonnull %a)
+  %tmp5 = tail call i32 @g(ptr noundef nonnull %a)
   ret i32 %tmp5
 
 hd:
@@ -1260,7 +1260,7 @@ define i32 @nonnull_exec_ctx_2b(ptr %a, i32 %b) willreturn nounwind {
 ; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; TUNIT:       ex:
-; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]]
+; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR5]]
 ; TUNIT-NEXT:    ret i32 [[TMP5]]
 ; TUNIT:       hd:
 ; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
@@ -1278,7 +1278,7 @@ define i32 @nonnull_exec_ctx_2b(ptr %a, i32 %b) willreturn nounwind {
 ; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
 ; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
 ; CGSCC:       ex:
-; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]]
+; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr noundef nonnull [[A]]) #[[ATTR4]]
 ; CGSCC-NEXT:    ret i32 [[TMP5]]
 ; CGSCC:       hd:
 ; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
@@ -1294,7 +1294,7 @@ en:
   br i1 %tmp3, label %ex, label %hd
 
 ex:
-  %tmp5 = tail call i32 @g(ptr nonnull %a)
+  %tmp5 = tail call i32 @g(ptr noundef nonnull %a)
   ret i32 %tmp5
 
 hd:
@@ -1512,10 +1512,10 @@ define ptr @nonnull_function_ptr_2() {
   ret ptr @function_decl
 }
 
-; FIXME: nonnull should not be propagated to the caller's p unless there is noundef
+; The nonnull attribute does not describe the caller's value without noundef.
 define void @nonnull_caller(ptr %p) {
 ; CHECK-LABEL: define {{[^@]+}}@nonnull_caller
-; CHECK-SAME: (ptr nonnull [[P:%.*]]) {
+; CHECK-SAME: (ptr [[P:%.*]]) {
 ; CHECK-NEXT:    call void @nonnull_callee(ptr nonnull [[P]])
 ; CHECK-NEXT:    ret void
 ;



More information about the llvm-commits mailing list