https://github.com/adams381 created 
https://github.com/llvm/llvm-project/pull/188281

Add `noalias` for `restrict`-qualified pointer parameters, `nonnull` for 
`__attribute__((nonnull))` pointer parameters (both per-param and function-wide 
forms), and `nonnull` on return values for functions with `ReturnsNonNullAttr` 
(e.g. `operator new`).

These are added to `constructFunctionArgumentAttributes` and 
`constructAttributeList`, extending the framework from #181052 and #182910.  
The argument function now takes `targetDecl` so it can access `ParmVarDecl` for 
source-level qualifiers (restrict) and attributes (nonnull) that aren't on the 
canonical `QualType`.


>From 8cbcb924d21d409a87de957f70d02b2998a58c74 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Tue, 24 Mar 2026 09:45:34 -0700
Subject: [PATCH] [CIR][ABI] Add restrict, nonnull, and ReturnsNonNull
 attributes

Add noalias for restrict-qualified pointer parameters, nonnull for
__attribute__((nonnull)) pointer parameters, and nonnull on return
values for functions with ReturnsNonNullAttr (e.g. operator new).

Pass targetDecl to constructFunctionArgumentAttributes so it can
access ParmVarDecl for source-level qualifiers and attributes that
are not on the canonical QualType.

Made-with: Cursor
---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          | 44 +++++++++++++--
 clang/lib/CIR/CodeGen/CIRGenModule.h          |  3 +-
 clang/test/CIR/CodeGen/coro-task.cpp          |  2 +-
 clang/test/CIR/CodeGen/new-delete.cpp         |  4 +-
 clang/test/CIR/CodeGen/new.cpp                | 56 +++++++++----------
 clang/test/CIR/CodeGen/restrict-nonnull.c     | 29 ++++++++++
 .../test/CIR/CodeGenBuiltins/builtin-call.cpp |  4 +-
 .../CodeGenBuiltins/builtin-new-delete.cpp    |  8 +--
 .../CIR/CodeGenBuiltins/builtin-printf.cpp    | 12 ++--
 9 files changed, 112 insertions(+), 50 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/restrict-nonnull.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 35479fa8097ce..e9e0909d2ae62 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -398,8 +398,13 @@ void CIRGenModule::constructAttributeList(
     attrs.set(cir::CIRDialect::getSideEffectAttrName(),
               cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
 
-    // TODO(cir): When doing 'return attrs' we need to cover the Restrict and
-    // ReturnsNonNull attributes here.
+    if (targetDecl->hasAttr<ReturnsNonNullAttr>())
+      retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
+                   mlir::UnitAttr::get(&getMLIRContext()));
+
+    // TODO(cir): Add noalias to returns for malloc-like functions
+    // (__attribute__((malloc)) / __declspec(restrict)).
+
     if (targetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
       addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
     // TODO(cir): Implement 'NoCFCheck' attribute here.  This requires
@@ -490,7 +495,7 @@ void CIRGenModule::constructAttributeList(
   // TODO(cir): Add loader-replaceable attribute here.
 
   constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
-  constructFunctionArgumentAttributes(info, isThunk, argAttrs);
+  constructFunctionArgumentAttributes(info, targetDecl, isThunk, argAttrs);
 }
 
 bool CIRGenModule::hasStrictReturn(QualType retTy, const Decl *targetDecl) {
@@ -626,13 +631,13 @@ void CIRGenModule::constructFunctionReturnAttributes(
 }
 
 void CIRGenModule::constructFunctionArgumentAttributes(
-    const CIRGenFunctionInfo &info, bool isThunk,
+    const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
     llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
   assert(!cir::MissingFeatures::abiArgInfo());
   // TODO(cir): classic codegen does a lot of work here based on the ABIArgInfo
   // to set things based on calling convention.
-  // At the moment, only nonnull, dereferenceable, align, and noundef are being
-  // implemented here, using similar logic to how we do so for return types.
+
+  const auto *fd = dyn_cast_or_null<FunctionDecl>(targetDecl);
 
   if (info.isInstanceMethod() && !isThunk) {
     QualType thisPtrTy = info.arguments()[0];
@@ -708,6 +713,33 @@ void CIRGenModule::constructFunctionArgumentAttributes(
             builder.getI64IntegerAttr(
                 getNaturalPointeeTypeAlignment(argType).getQuantity()));
     }
+
+    // Source-level parameter attributes (restrict, nonnull).  These
+    // require the FunctionDecl to access ParmVarDecl info.
+    if (fd) {
+      unsigned paramIdx = &argAttrList - argAttrs.data();
+      unsigned srcIdx = info.isInstanceMethod() ? paramIdx - 1 : paramIdx;
+      if (srcIdx < fd->getNumParams()) {
+        const ParmVarDecl *pvd = fd->getParamDecl(srcIdx);
+        QualType pvdType = pvd->getType();
+
+        // restrict on pointer parameters → noalias.
+        if (pvdType->isPointerType() && pvdType.isRestrictQualified())
+          argAttrList.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
+                          mlir::UnitAttr::get(&getMLIRContext()));
+
+        // __attribute__((nonnull)) on pointer parameters.
+        if (pvdType->isPointerType() && !codeGenOpts.NullPointerIsValid) {
+          bool hasNonnull = pvd->hasAttr<NonNullAttr>();
+          if (!hasNonnull)
+            if (const auto *nna = fd->getAttr<NonNullAttr>())
+              hasNonnull = nna->isNonNull(srcIdx);
+          if (hasNonnull)
+            argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
+                            mlir::UnitAttr::get(&getMLIRContext()));
+        }
+      }
+    }
   }
 }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 266510de84fd0..73fe8a6804957 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -117,7 +117,8 @@ class CIRGenModule : public CIRGenTypeCache {
                                          mlir::NamedAttrList &retAttrs);
   /// A helper for constructAttributeList that handles argument attributes.
   void constructFunctionArgumentAttributes(
-      const CIRGenFunctionInfo &info, bool isThunk,
+      const CIRGenFunctionInfo &info, const clang::Decl *targetDecl,
+      bool isThunk,
       llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs);
   /// A helper function for constructAttributeList that determines whether a
   /// return value might have been discarded.
diff --git a/clang/test/CIR/CodeGen/coro-task.cpp 
b/clang/test/CIR/CodeGen/coro-task.cpp
index b52f0f1871079..b5dbf5d11df60 100644
--- a/clang/test/CIR/CodeGen/coro-task.cpp
+++ b/clang/test/CIR/CodeGen/coro-task.cpp
@@ -176,7 +176,7 @@ VoidTask silly_task() {
 // CIR: cir.store{{.*}} %[[NullPtr]], %[[SavedFrameAddr]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CIR: cir.if %[[ShouldAlloc]] {
 // CIR:   %[[CoroSize:.*]] = cir.call @__builtin_coro_size() : () -> (!u64i 
{llvm.noundef})
-// CIR:   %[[AllocAddr:.*]] = cir.call @_Znwm(%[[CoroSize]]) {allocsize = 
array<i32: 0>} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.noundef})
+// CIR:   %[[AllocAddr:.*]] = cir.call @_Znwm(%[[CoroSize]]) {allocsize = 
array<i32: 0>} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.nonnull, 
llvm.noundef})
 // CIR:   cir.store{{.*}} %[[AllocAddr]], %[[SavedFrameAddr]] : 
!cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
 // CIR: }
 // CIR: %[[Load0:.*]] = cir.load{{.*}} %[[SavedFrameAddr]] : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
diff --git a/clang/test/CIR/CodeGen/new-delete.cpp 
b/clang/test/CIR/CodeGen/new-delete.cpp
index d0c8c7d851c70..c0cb843d3b68b 100644
--- a/clang/test/CIR/CodeGen/new-delete.cpp
+++ b/clang/test/CIR/CodeGen/new-delete.cpp
@@ -31,7 +31,7 @@ A *a() {
 // LLVM: define {{.*}} ptr @_Z1av() {{.*}} personality ptr 
@__gxx_personality_v0 {
 // LLVM:   %[[RETVAL:.*]] = alloca ptr
 // LLVM:   %[[NEW_RESULT:.*]] = alloca ptr
-// LLVM:   %[[PTR:.*]] = call ptr @_Znwm(i64 8) #[[ATTR_BUILTIN_NEW:.*]]
+// LLVM:   %[[PTR:.*]] = call nonnull ptr @_Znwm(i64 8) 
#[[ATTR_BUILTIN_NEW:.*]]
 // LLVM:   br label %[[EH_SCOPE:.*]]
 // LLVM: [[EH_SCOPE]]:
 // LLVM:   store ptr %[[PTR]], ptr %[[NEW_RESULT]]
@@ -106,7 +106,7 @@ A *b() {
 // LLVM: define {{.*}} ptr @_Z1bv() {{.*}} personality ptr 
@__gxx_personality_v0 {
 // LLVM:   %[[RETVAL:.*]] = alloca ptr
 // LLVM:   %[[NEW_RESULT:.*]] = alloca ptr
-// LLVM:   %[[PTR:.*]] = call ptr @_Znwm(i64 8) #[[ATTR_BUILTIN_NEW]]
+// LLVM:   %[[PTR:.*]] = call nonnull ptr @_Znwm(i64 8) #[[ATTR_BUILTIN_NEW]]
 // LLVM:   br label %[[EH_SCOPE:.*]]
 // LLVM: [[EH_SCOPE]]:
 // LLVM:   store ptr %[[PTR]], ptr %[[NEW_RESULT]]
diff --git a/clang/test/CIR/CodeGen/new.cpp b/clang/test/CIR/CodeGen/new.cpp
index 1062b5867d0d6..4db951322e98c 100644
--- a/clang/test/CIR/CodeGen/new.cpp
+++ b/clang/test/CIR/CodeGen/new.cpp
@@ -163,7 +163,7 @@ void test_new_with_complex_type() {
 // CHECK: cir.func{{.*}} @_Z26test_new_with_complex_typev
 // CHECK:   %[[A_ADDR:.*]] = cir.alloca !cir.ptr<!cir.complex<!cir.float>>, 
!cir.ptr<!cir.ptr<!cir.complex<!cir.float>>>, ["a", init]
 // CHECK:   %[[COMPLEX_SIZE:.*]] = cir.const #cir.int<8> : !u64i
-// CHECK:   %[[NEW_COMPLEX:.*]] = cir.call @_Znwm(%[[COMPLEX_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:   %[[NEW_COMPLEX:.*]] = cir.call @_Znwm(%[[COMPLEX_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:   %[[COMPLEX_PTR:.*]] = cir.cast bitcast %[[NEW_COMPLEX]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.complex<!cir.float>>
 // CHECK:   %[[COMPLEX_VAL:.*]] = cir.const 
#cir.const_complex<#cir.fp<1.000000e+00> : !cir.float, #cir.fp<2.000000e+00> : 
!cir.float> : !cir.complex<!cir.float>
 // CHECK:   cir.store{{.*}} %[[COMPLEX_VAL]], %[[COMPLEX_PTR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
@@ -171,7 +171,7 @@ void test_new_with_complex_type() {
 
 // LLVM: define{{.*}} void @_Z26test_new_with_complex_typev
 // LLVM:   %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[NEW_COMPLEX:.*]] = call noundef ptr @_Znwm(i64 noundef 8)
+// LLVM:   %[[NEW_COMPLEX:.*]] = call noundef nonnull ptr @_Znwm(i64 noundef 8)
 // LLVM:   store { float, float } { float 1.000000e+00, float 2.000000e+00 }, 
ptr %[[NEW_COMPLEX]], align 8
 // LLVM:   store ptr %[[NEW_COMPLEX]], ptr %[[A_ADDR]], align 8
 
@@ -191,7 +191,7 @@ void t_new_constant_size() {
 // CHECK:   cir.func{{.*}} @_Z19t_new_constant_sizev()
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!cir.double>, 
!cir.ptr<!cir.ptr<!cir.double>>, ["p", init] {alignment = 8 : i64}
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<128> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[TYPED_PTR:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.double>
 // CHECK:    cir.store align(8) %[[TYPED_PTR]], %[[P_ADDR]] : 
!cir.ptr<!cir.double>, !cir.ptr<!cir.ptr<!cir.double>>
 // CHECK:    cir.return
@@ -199,7 +199,7 @@ void t_new_constant_size() {
 
 // LLVM: define{{.*}} void @_Z19t_new_constant_sizev
 // LLVM:   %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[CALL:.*]] = call noundef ptr @_Znam(i64 noundef 128)
+// LLVM:   %[[CALL:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 128)
 // LLVM:   store ptr %[[CALL]], ptr %[[P_ADDR]], align 8
 
 // OGCG: define{{.*}} void @_Z19t_new_constant_sizev
@@ -220,7 +220,7 @@ void t_constant_size_nontrivial() {
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C>, 
!cir.ptr<!cir.ptr<!rec_C>>, ["p", init] {alignment = 8 : i64}
 // CHECK:    %[[NUM_ELEMENTS:.*]] = cir.const #cir.int<3> : !u64i
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<11> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_BASE]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
 // CHECK:    cir.store align(8) %[[NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
@@ -234,7 +234,7 @@ void t_constant_size_nontrivial() {
 
 // LLVM: @_Z26t_constant_size_nontrivialv()
 // LLVM:   %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[COOKIE_PTR:.*]] = call noundef ptr @_Znam(i64 noundef 11)
+// LLVM:   %[[COOKIE_PTR:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 11)
 // LLVM:   store i64 3, ptr %[[COOKIE_PTR]], align 8
 // LLVM:   %[[ALLOCATED_PTR:.*]] = getelementptr ptr, ptr %[[COOKIE_PTR]], i64 
8
 // LLVM:   store ptr %[[ALLOCATED_PTR]], ptr %[[ALLOCA]], align 8
@@ -260,7 +260,7 @@ void t_constant_size_nontrivial2() {
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_D>, 
!cir.ptr<!cir.ptr<!rec_D>>, ["p", init] {alignment = 8 : i64}
 // CHECK:    %[[NUM_ELEMENTS:.*]] = cir.const #cir.int<3> : !u64i
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<20> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_BASE]] : 
!cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
 // CHECK:    cir.store align(8) %[[NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, 
!cir.ptr<!u64i>
@@ -274,7 +274,7 @@ void t_constant_size_nontrivial2() {
 
 // LLVM: @_Z27t_constant_size_nontrivial2v()
 // LLVM:   %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[COOKIE_PTR:.*]] = call noundef ptr @_Znam(i64 noundef 20)
+// LLVM:   %[[COOKIE_PTR:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 20)
 // LLVM:   store i64 3, ptr %[[COOKIE_PTR]], align 8
 // LLVM:   %[[ALLOCATED_PTR:.*]] = getelementptr ptr, ptr %[[COOKIE_PTR]], i64 
8
 // LLVM:   store ptr %[[ALLOCATED_PTR]], ptr %[[ALLOCA]], align 8
@@ -292,7 +292,7 @@ void t_align16_nontrivial() {
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_E>, 
!cir.ptr<!cir.ptr<!rec_E>>, ["p", init] {alignment = 8 : i64}
 // CHECK:    %[[NUM_ELEMENTS:.*]] = cir.const #cir.int<2> : !u64i
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<48> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
 // CHECK:    %[[COOKIE_OFFSET:.*]] = cir.const #cir.int<8> : !s32i
 // CHECK:    %[[COOKIE_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], 
%[[COOKIE_OFFSET]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> 
!cir.ptr<!cir.ptr<!u8i>>
@@ -308,7 +308,7 @@ void t_align16_nontrivial() {
 
 // LLVM: @_Z20t_align16_nontrivialv()
 // LLVM:   %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[RAW_PTR:.*]] = call noundef ptr @_Znam(i64 noundef 48)
+// LLVM:   %[[RAW_PTR:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 48)
 // LLVM:   %[[COOKIE_PTR:.*]] = getelementptr ptr, ptr %[[RAW_PTR]], i64 8
 // LLVM:   store i64 2, ptr %[[COOKIE_PTR]], align 8
 // LLVM:   %[[ALLOCATED_PTR:.*]] = getelementptr ptr, ptr %[[RAW_PTR]], i64 16
@@ -330,14 +330,14 @@ void t_new_multidim_constant_size() {
 // CHECK:  cir.func{{.*}} @_Z28t_new_multidim_constant_sizev()
 // CHECK:    %[[P_ADDR:.*]] = cir.alloca 
!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>, 
!cir.ptr<!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>>, ["p", init] 
{alignment = 8 : i64}
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<192> : !u64i
-// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[RAW_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[TYPED_PTR:.*]] = cir.cast bitcast %[[RAW_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>
 // CHECK:    cir.store align(8) %[[TYPED_PTR]], %[[P_ADDR]] : 
!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>, 
!cir.ptr<!cir.ptr<!cir.array<!cir.array<!cir.double x 4> x 3>>>
 // CHECK:  }
 
 // LLVM: define{{.*}} void @_Z28t_new_multidim_constant_sizev
 // LLVM:   %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[CALL:.*]] = call noundef ptr @_Znam(i64 noundef 192)
+// LLVM:   %[[CALL:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 192)
 // LLVM:   store ptr %[[CALL]], ptr %[[P_ADDR]], align 8
 
 // OGCG: define{{.*}} void @_Z28t_new_multidim_constant_sizev
@@ -351,14 +351,14 @@ void t_constant_size_memset_init() {
 
 // CHECK:  cir.func {{.*}} @_Z27t_constant_size_memset_initv()
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<64> : !u64i
-// CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[ELEM_PTR:.*]] = cir.cast bitcast %[[ALLOC_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!s32i>
 // CHECK:    %[[VOID_PTR:.*]] = cir.cast bitcast %[[ELEM_PTR]] : 
!cir.ptr<!s32i> -> !cir.ptr<!void>
 // CHECK:    %[[ZERO:.*]] = cir.const #cir.int<0> : !u8i
 // CHECK:    cir.libc.memset %[[ALLOCATION_SIZE]] bytes at %[[VOID_PTR]] to 
%[[ZERO]] : !cir.ptr<!void>, !u8i, !u64i
 
 // LLVM: define {{.*}} void @_Z27t_constant_size_memset_initv()
-// LLVM:   %[[P:.*]] = call noundef ptr @_Znam(i64 noundef 64)
+// LLVM:   %[[P:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 64)
 // LLVM:   call void @llvm.memset.p0.i64(ptr %[[P]], i8 0, i64 64, i1 false)
 
 // OGCG: define {{.*}} void @_Z27t_constant_size_memset_initv()
@@ -371,7 +371,7 @@ void t_constant_size_full_init() {
 
 // CHECK:  cir.func {{.*}} @_Z25t_constant_size_full_initv()
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<16> : !u64i
-// CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[ELEM_0_PTR:.*]] = cir.cast bitcast %[[ALLOC_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!s32i>
 // CHECK:    %[[CONST_ONE:.*]] = cir.const #cir.int<1> : !s32i
 // CHECK:    cir.store{{.*}} %[[CONST_ONE]], %[[ELEM_0_PTR]] : !s32i, 
!cir.ptr<!s32i>
@@ -389,7 +389,7 @@ void t_constant_size_full_init() {
 // CHECK:    cir.store{{.*}} %[[CONST_FOUR]], %[[ELEM_3_PTR]] : !s32i, 
!cir.ptr<!s32i>
 
 // LLVM: define {{.*}} void @_Z25t_constant_size_full_initv()
-// LLVM:   %[[P:.*]] = call noundef ptr @_Znam(i64 noundef 16)
+// LLVM:   %[[P:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 16)
 // LLVM:   store i32 1, ptr %[[CALL]]
 // LLVM:   %[[ELEM_1:.*]] = getelementptr i32, ptr %[[P]], i64 1
 // LLVM:   store i32 2, ptr %[[ELEM_1]]
@@ -414,7 +414,7 @@ void t_constant_size_partial_init() {
 
 // CHECK:  cir.func {{.*}} @_Z28t_constant_size_partial_initv()
 // CHECK:    %[[ALLOCATION_SIZE:.*]] = cir.const #cir.int<64> : !u64i
-// CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.noundef})
+// CHECK:    %[[ALLOC_PTR:.*]] = cir.call @_Znam(%[[ALLOCATION_SIZE]]) 
{allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> 
(!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
 // CHECK:    %[[ELEM_0_PTR:.*]] = cir.cast bitcast %[[ALLOC_PTR]] : 
!cir.ptr<!void> -> !cir.ptr<!s32i>
 // CHECK:    %[[CONST_ONE:.*]] = cir.const #cir.int<1> : !s32i
 // CHECK:    cir.store{{.*}} %[[CONST_ONE]], %[[ELEM_0_PTR]] : !s32i, 
!cir.ptr<!s32i>
@@ -435,7 +435,7 @@ void t_constant_size_partial_init() {
 // CHECK:    cir.libc.memset %[[REMAINING_SIZE]] bytes at %[[VOID_PTR]] to 
%[[ZERO]] : !cir.ptr<!void>, !u8i, !u64i
 
 // LLVM: define {{.*}} void @_Z28t_constant_size_partial_initv()
-// LLVM:   %[[P:.*]] = call noundef ptr @_Znam(i64 {{.*}} 64)
+// LLVM:   %[[P:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 64)
 // LLVM:   store i32 1, ptr %[[P]]
 // LLVM:   %[[ELEM_1:.*]] = getelementptr i32, ptr %[[P]], i64 1
 // LLVM:   store i32 2, ptr %[[ELEM_1]]
@@ -464,7 +464,7 @@ void t_new_var_size(size_t n) {
 
 // LLVM: define{{.*}} void @_Z14t_new_var_sizem
 // LLVM:   %[[N:.*]] = load i64, ptr %{{.+}}
-// LLVM:   %[[PTR:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[N]])
+// LLVM:   %[[PTR:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} %[[N]])
 
 // OGCG: define{{.*}} void @_Z14t_new_var_sizem
 // OGCG:   %[[N:.*]] = load i64, ptr %{{.+}}
@@ -482,7 +482,7 @@ void t_new_var_size2(int n) {
 // LLVM: define{{.*}} void @_Z15t_new_var_size2i
 // LLVM:   %[[N:.*]] = load i32, ptr %{{.+}}
 // LLVM:   %[[N_SIZE_T:.*]] = sext i32 %[[N]] to i64
-// LLVM:   %[[PTR:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[N_SIZE_T]])
+// LLVM:   %[[PTR:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 
%[[N_SIZE_T]])
 
 // OGCG: define{{.*}} void @_Z15t_new_var_size2i
 // OGCG:   %[[N:.*]] = load i32, ptr %{{.+}}
@@ -507,7 +507,7 @@ void t_new_var_size3(size_t n) {
 // LLVM:   %[[ELEMENT_SIZE:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 0
 // LLVM:   %[[OVERFLOW:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 1
 // LLVM:   %[[ALLOC_SIZE:.*]] = select i1 %[[OVERFLOW]], i64 -1, i64 
%[[ELEMENT_SIZE]]
-// LLVM:   %[[RESULT:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[ALLOC_SIZE]])
+// LLVM:   %[[RESULT:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 
%[[ALLOC_SIZE]])
 
 // OGCG: define{{.*}} void @_Z15t_new_var_size3m
 // OGCG:   %[[N:.*]] = load i64, ptr %{{.+}}
@@ -537,7 +537,7 @@ void t_new_var_size4(int n) {
 // LLVM:   %[[ELEMENT_SIZE:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 0
 // LLVM:   %[[OVERFLOW:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 1
 // LLVM:   %[[ALLOC_SIZE:.*]] = select i1 %[[OVERFLOW]], i64 -1, i64 
%[[ELEMENT_SIZE]]
-// LLVM:   %[[PTR:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[ALLOC_SIZE]])
+// LLVM:   %[[PTR:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 
%[[ALLOC_SIZE]])
 
 // OGCG: define{{.*}} void @_Z15t_new_var_size4i
 // OGCG:   %[[N:.*]] = load i32, ptr %{{.+}}
@@ -571,7 +571,7 @@ void t_new_var_size5(int n) {
 // LLVM:   %[[ELEMENT_SIZE:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 0
 // LLVM:   %[[OVERFLOW:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 1
 // LLVM:   %[[ALLOC_SIZE:.*]] = select i1 %[[OVERFLOW]], i64 -1, i64 
%[[ELEMENT_SIZE]]
-// LLVM:   %[[PTR:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[ALLOC_SIZE]])
+// LLVM:   %[[PTR:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 
%[[ALLOC_SIZE]])
 
 // OGCG: define{{.*}} void @_Z15t_new_var_size5i
 // OGCG:   %[[N:.*]] = load i32, ptr %{{.+}}
@@ -625,7 +625,7 @@ void t_new_var_size6(int n) {
 // LLVM:   %[[OVERFLOW:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 1
 // LLVM:   %[[ANY_OVERFLOW:.*]] = or i1 %[[LT_MIN_SIZE]], %[[OVERFLOW]]
 // LLVM:   %[[ALLOC_SIZE:.*]] = select i1 %[[ANY_OVERFLOW]], i64 -1, i64 
%[[ELEMENT_SIZE]]
-// LLVM:   %[[PTR:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[ALLOC_SIZE]])
+// LLVM:   %[[PTR:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 
%[[ALLOC_SIZE]])
 // LLVM:   store double 1.000000e+00, ptr %[[PTR]], align 8
 // LLVM:   %[[ELEM_1:.*]] = getelementptr double, ptr %[[PTR]], i64 1
 // LLVM:   store double 2.000000e+00, ptr %[[ELEM_1]], align 8
@@ -674,7 +674,7 @@ void t_new_var_size7(__int128 n) {
 // LLVM:   %[[ELEMENT_SIZE:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 0
 // LLVM:   %[[OVERFLOW:.*]] = extractvalue { i64, i1 } %[[MUL_OVERFLOW]], 1
 // LLVM:   %[[ALLOC_SIZE:.*]] = select i1 %[[OVERFLOW]], i64 -1, i64 
%[[ELEMENT_SIZE]]
-// LLVM:   %[[PTR:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[ALLOC_SIZE]])
+// LLVM:   %[[PTR:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 
%[[ALLOC_SIZE]])
 
 // OGCG: define{{.*}} void @_Z15t_new_var_size7n
 // OGCG:   %[[N:.*]] = load i128, ptr %{{.+}}
@@ -710,7 +710,7 @@ void t_new_var_size_nontrivial(size_t n) {
 // LLVM:   %[[OVERFLOW_ADD:.*]] = extractvalue { i64, i1 } %[[ADD_OVERFLOW]], 1
 // LLVM:   %[[ANY_OVERFLOW:.*]] = or i1 %[[OVERFLOW]], %[[OVERFLOW_ADD]]
 // LLVM:   %[[ALLOC_SIZE:.*]] = select i1 %[[ANY_OVERFLOW]], i64 -1, i64 
%[[ELEMENT_SIZE]]
-// LLVM:   %[[PTR:.*]] = call noundef ptr @_Znam(i64 {{.*}} %[[ALLOC_SIZE]])
+// LLVM:   %[[PTR:.*]] = call noundef nonnull ptr @_Znam(i64 {{.*}} 
%[[ALLOC_SIZE]])
 
 // OGCG: define{{.*}} void @_Z25t_new_var_size_nontrivialm
 // OGCG:   %[[N:.*]] = load i64, ptr %{{.+}}
@@ -775,7 +775,7 @@ void test_array_new_with_ctor_init() {
 
 // LLVM: define{{.*}} void @_Z29test_array_new_with_ctor_initv
 // LLVM:   %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[RAW_PTR:.*]] = call noundef ptr @_Znam(i64 noundef 3)
+// LLVM:   %[[RAW_PTR:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 3)
 // LLVM:   %[[BEGIN:.*]] = getelementptr %class.F, ptr %[[RAW_PTR]], i32 0
 // LLVM:   %[[ARRAY_END:.*]] = getelementptr %class.F, ptr %[[BEGIN]], i64 3
 // LLVM:   %[[IDX_ADDR:.*]] = alloca ptr, i64 1, align 1
@@ -874,7 +874,7 @@ void test_array_new_with_ctor_partial_init_list() {
 
 // LLVM: define{{.*}} void @_Z42test_array_new_with_ctor_partial_init_listv
 // LLVM:   %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8
-// LLVM:   %[[RAW_PTR:.*]] = call noundef ptr @_Znam(i64 noundef 8)
+// LLVM:   %[[RAW_PTR:.*]] = call noundef nonnull ptr @_Znam(i64 noundef 8)
 // LLVM:   call void @_ZN1GC1Ei(ptr noundef nonnull align 1 dereferenceable(1) 
%[[RAW_PTR]], i32 noundef 1)
 // LLVM:   %[[SECOND:.*]] = getelementptr %class.G, ptr %[[RAW_PTR]], i64 1
 // LLVM:   call void @_ZN1GC1Ei(ptr noundef nonnull align 1 dereferenceable(1) 
%[[SECOND]], i32 noundef 2)
diff --git a/clang/test/CIR/CodeGen/restrict-nonnull.c 
b/clang/test/CIR/CodeGen/restrict-nonnull.c
new file mode 100644
index 0000000000000..d391ac1b36809
--- /dev/null
+++ b/clang/test/CIR/CodeGen/restrict-nonnull.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+// restrict on pointer params adds noalias.
+void take_restrict(int *restrict p) { *p = 42; }
+// CIR: cir.func {{.*}} @take_restrict(%arg0: !cir.ptr<!s32i>
+// CIR-SAME: {llvm.noalias, llvm.noundef}
+// LLVM: define {{.*}} void @take_restrict(ptr noalias noundef %{{.*}})
+// OGCG: define {{.*}} void @take_restrict(ptr noalias noundef %{{.*}})
+
+// __attribute__((nonnull)) on individual parameter.
+void take_nonnull(int *p) __attribute__((nonnull(1)));
+void take_nonnull(int *p) { *p = 42; }
+// CIR: cir.func {{.*}} @take_nonnull(%arg0: !cir.ptr<!s32i>
+// CIR-SAME: {llvm.nonnull, llvm.noundef}
+// LLVM: define {{.*}} void @take_nonnull(ptr noundef nonnull %{{.*}})
+// OGCG: define {{.*}} void @take_nonnull(ptr noundef nonnull %{{.*}})
+
+// restrict + nonnull together.
+void take_both(int *restrict p) __attribute__((nonnull(1)));
+void take_both(int *restrict p) { *p = 42; }
+// CIR: cir.func {{.*}} @take_both(%arg0: !cir.ptr<!s32i>
+// CIR-SAME: {llvm.noalias, llvm.nonnull, llvm.noundef}
+// LLVM: define {{.*}} void @take_both(ptr noalias noundef nonnull %{{.*}})
+// OGCG: define {{.*}} void @take_both(ptr noalias noundef nonnull %{{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-call.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtin-call.cpp
index d6f72b115f183..0efb6c7ae78ef 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-call.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-call.cpp
@@ -85,11 +85,11 @@ void library_builtins() {
 
 // CIR: cir.func{{.*}} @_Z16library_builtinsv()
 // CIR: %[[NULL:.+]] = cir.const #cir.ptr<null> : !cir.ptr<!s8i>
-// CIR: cir.call @printf(%[[NULL]]) nothrow : (!cir.ptr<!s8i> {llvm.noundef}) 
-> !s32i
+// CIR: cir.call @printf(%[[NULL]]) nothrow : (!cir.ptr<!s8i> {llvm.noalias, 
llvm.noundef}) -> !s32i
 // CIR: cir.call @abort() nothrow {noreturn} : () -> ()
 
 // LLVM: define{{.*}} void @_Z16library_builtinsv()
-// LLVM: call i32 (ptr, ...) @printf(ptr noundef null)
+// LLVM: call i32 (ptr, ...) @printf(ptr noalias noundef null)
 // LLVM: call void @abort()
 
 // OGCG: define{{.*}} void @_Z16library_builtinsv()
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-new-delete.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtin-new-delete.cpp
index fdb4250af06d6..3ddf165e767c2 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-new-delete.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-new-delete.cpp
@@ -9,12 +9,12 @@
 void test_builtins_basic() {
   __builtin_operator_delete(__builtin_operator_new(4));
   // CIR-LABEL: test_builtins_basic
-  // CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) {allocsize = array<i32: 0>, 
builtin} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.noundef})
+  // CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) {allocsize = array<i32: 0>, 
builtin} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.nonnull, 
llvm.noundef})
   // CIR: cir.call @_ZdlPv([[P]]) {{.*}}builtin{{.*}} : (!cir.ptr<!void> 
{llvm.noundef}) -> ()
   // CIR: cir.return
 
   // LLVM-LABEL: test_builtins_basic
-  // LLVM: [[P:%.*]] = call noundef ptr @_Znwm(i64 {{.*}} 4) 
#[[ATTR_BUILTIN_NEW:.*]]
+  // LLVM: [[P:%.*]] = call noundef nonnull ptr @_Znwm(i64 {{.*}} 4) 
#[[ATTR_BUILTIN_NEW:.*]]
   // LLVM: call void @_ZdlPv(ptr {{.*}} [[P]]) #[[ATTR_BUILTIN_DEL:.*]]
   // LLVM: ret void
 
@@ -28,12 +28,12 @@ void test_sized_delete() {
   __builtin_operator_delete(__builtin_operator_new(4), 4);
 
   // CIR-LABEL: test_sized_delete
-  // CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) {allocsize = array<i32: 0>, 
builtin} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.noundef})
+  // CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) {allocsize = array<i32: 0>, 
builtin} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.nonnull, 
llvm.noundef})
   // CIR: cir.call @_ZdlPvm([[P]], {{%.*}}) {{.*}}builtin{{.*}} : 
(!cir.ptr<!void> {llvm.noundef}, !u64i {llvm.noundef}) -> ()
   // CIR: cir.return
 
   // LLVM-LABEL: test_sized_delete
-  // LLVM: [[P:%.*]] = call noundef ptr @_Znwm(i64 {{.*}} 4) 
#[[ATTR_BUILTIN_NEW]]
+  // LLVM: [[P:%.*]] = call noundef nonnull ptr @_Znwm(i64 {{.*}} 4) 
#[[ATTR_BUILTIN_NEW]]
   // LLVM: call void @_ZdlPvm(ptr {{.*}} [[P]], i64 {{.*}} 4) 
#[[ATTR_BUILTIN_DEL]]
   // LLVM: ret void
 
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-printf.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtin-printf.cpp
index 2a0f5c4196a8d..5c2ee802f7076 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-printf.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-printf.cpp
@@ -26,16 +26,16 @@ void func(char const * const str, int i) {
 // CIR:   cir.store %[[arg0]], %[[str_ptr]] : !cir.ptr<!s8i>, 
!cir.ptr<!cir.ptr<!s8i>>
 // CIR:   cir.store %[[arg1]], %[[i_ptr]] : !s32i, !cir.ptr<!s32i>
 // CIR:   %[[null_ptr:.+]] = cir.const #cir.ptr<null> : !cir.ptr<!s8i>
-// CIR:   %[[printf_result1:.+]] = cir.call @printf(%[[null_ptr]]) nothrow : 
(!cir.ptr<!s8i> {llvm.noundef}) -> !s32i
+// CIR:   %[[printf_result1:.+]] = cir.call @printf(%[[null_ptr]]) nothrow : 
(!cir.ptr<!s8i> {llvm.noalias, llvm.noundef}) -> !s32i
 // CIR:   %[[str_fmt_global:.+]] = cir.get_global @".str" : 
!cir.ptr<!cir.array<!s8i x 3>>
 // CIR:   %[[str_fmt_ptr:.+]] = cir.cast array_to_ptrdecay %[[str_fmt_global]] 
: !cir.ptr<!cir.array<!s8i x 3>> -> !cir.ptr<!s8i>
 // CIR:   %[[str_val:.+]] = cir.load{{.*}} %[[str_ptr]] : 
!cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
-// CIR:   %[[printf_result2:.+]] = cir.call @printf(%[[str_fmt_ptr]], 
%[[str_val]]) nothrow : (!cir.ptr<!s8i> {llvm.noundef}, !cir.ptr<!s8i> 
{llvm.noundef}) -> !s32i
+// CIR:   %[[printf_result2:.+]] = cir.call @printf(%[[str_fmt_ptr]], 
%[[str_val]]) nothrow : (!cir.ptr<!s8i> {llvm.noalias, llvm.noundef}, 
!cir.ptr<!s8i> {llvm.noundef}) -> !s32i
 // CIR:   %[[full_fmt_global:.+]] = cir.get_global @".str.1" : 
!cir.ptr<!cir.array<!s8i x 7>>
 // CIR:   %[[full_fmt_ptr:.+]] = cir.cast array_to_ptrdecay 
%[[full_fmt_global]] : !cir.ptr<!cir.array<!s8i x 7>> -> !cir.ptr<!s8i>
 // CIR:   %[[str_val2:.+]] = cir.load{{.*}} %[[str_ptr]] : 
!cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
 // CIR:   %[[i_val:.+]] = cir.load{{.*}} %[[i_ptr]] : !cir.ptr<!s32i>, !s32i
-// CIR:   %[[printf_result3:.+]] = cir.call @printf(%[[full_fmt_ptr]], 
%[[str_val2]], %[[i_val]]) nothrow : (!cir.ptr<!s8i> {llvm.noundef}, 
!cir.ptr<!s8i> {llvm.noundef}, !s32i {llvm.noundef}) -> !s32i
+// CIR:   %[[printf_result3:.+]] = cir.call @printf(%[[full_fmt_ptr]], 
%[[str_val2]], %[[i_val]]) nothrow : (!cir.ptr<!s8i> {llvm.noalias, 
llvm.noundef}, !cir.ptr<!s8i> {llvm.noundef}, !s32i {llvm.noundef}) -> !s32i
 // CIR:   cir.return
 
 // LLVM: define{{.*}} void @_Z4funcPKci(ptr noundef %[[arg0:.+]], i32 noundef 
%[[arg1:.+]])
@@ -43,12 +43,12 @@ void func(char const * const str, int i) {
 // LLVM:   %[[i_ptr:.+]] = alloca i32
 // LLVM:   store ptr %[[arg0]], ptr %[[str_ptr]]{{.*}}
 // LLVM:   store i32 %[[arg1]], ptr %[[i_ptr]]{{.*}}
-// LLVM:   %[[printf_result1:.+]] = call i32 (ptr, ...) @printf(ptr noundef 
null)
+// LLVM:   %[[printf_result1:.+]] = call i32 (ptr, ...) @printf(ptr noalias 
noundef null)
 // LLVM:   %[[str_val:.+]] = load ptr, ptr %[[str_ptr]]{{.*}}
-// LLVM:   %[[printf_result2:.+]] = call i32 (ptr, ...) @printf(ptr noundef 
@.str, ptr noundef %[[str_val]])
+// LLVM:   %[[printf_result2:.+]] = call i32 (ptr, ...) @printf(ptr noalias 
noundef @.str, ptr noundef %[[str_val]])
 // LLVM:   %[[str_val2:.+]] = load ptr, ptr %[[str_ptr]]{{.*}}
 // LLVM:   %[[i_val:.+]] = load i32, ptr %[[i_ptr]]{{.*}}
-// LLVM:   %[[printf_result3:.+]] = call i32 (ptr, ...) @printf(ptr noundef 
@.str.1, ptr noundef %[[str_val2]], i32 noundef %[[i_val]])
+// LLVM:   %[[printf_result3:.+]] = call i32 (ptr, ...) @printf(ptr noalias 
noundef @.str.1, ptr noundef %[[str_val2]], i32 noundef %[[i_val]])
 // LLVM:   ret void
 
 // OGCG: define{{.*}} void @_Z4funcPKci(ptr noundef %[[arg0:.+]], i32 noundef 
%[[arg1:.+]])

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to