https://github.com/erichkeane updated 
https://github.com/llvm/llvm-project/pull/177978

>From e923db15e33e28a80a19270a868e4e73bcf3d7ef Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Tue, 20 Jan 2026 08:31:54 -0800
Subject: [PATCH 1/4] [CIR] Implement 'noreturn' attribute for functions/calls.

This mirrors what LLVM does, and requires propagating into the LLVM
dialect: When the user specifies 'noreturn' we propagate this down
throughout the stack.

Note the similar 'willreturn' is too strong of a guarantee (in that they
are not opposites of each other, as there is a 'unknown' implied by all
others), so we cannot use that on non-noreturn functions.
---
 .../clang/CIR/Dialect/IR/CIRDialect.td        |  1 +
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          | 48 +++++++++++++++---
 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h    | 26 ++++++++--
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp         | 11 ++---
 clang/lib/CIR/CodeGen/CIRGenTypes.h           |  2 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 13 ++++-
 clang/test/CIR/CodeGen/noreturn.cpp           | 49 +++++++++++++++++++
 .../test/CIR/CodeGenBuiltins/builtin_call.cpp |  2 +-
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   |  2 +
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp    |  4 ++
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp        |  2 +
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       |  1 +
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |  2 +
 13 files changed, 141 insertions(+), 22 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/noreturn.cpp

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 7c38492544b39..058f096bfae3b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -39,6 +39,7 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
     static llvm::StringRef getCalleeAttrName() { return "callee"; }
     static llvm::StringRef getNoThrowAttrName() { return "nothrow"; }
+    static llvm::StringRef getNoReturnAttrName() { return "no_return"; }
     static llvm::StringRef getSideEffectAttrName() { return "side_effect"; }
     static llvm::StringRef getModuleLevelAsmAttrName() { return 
"cir.module_asm"; }
     static llvm::StringRef getGlobalCtorsAttrName() { return 
"cir.global_ctors"; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 5fd11c6d97c07..628f39ae2cfba 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -21,7 +21,7 @@ using namespace clang;
 using namespace clang::CIRGen;
 
 CIRGenFunctionInfo *
-CIRGenFunctionInfo::create(CanQualType resultType,
+CIRGenFunctionInfo::create(FunctionType::ExtInfo info, CanQualType resultType,
                            llvm::ArrayRef<CanQualType> argTypes,
                            RequiredArgs required) {
   // The first slot allocated for arg type slot is for the return value.
@@ -32,6 +32,8 @@ CIRGenFunctionInfo::create(CanQualType resultType,
 
   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
 
+  fi->noReturn = info.getNoReturn();
+
   fi->required = required;
   fi->numArgs = argTypes.size();
 
@@ -120,6 +122,11 @@ void CIRGenModule::constructAttributeList(llvm::StringRef 
name,
   assert(!cir::MissingFeatures::opCallCallConv());
   sideEffect = cir::SideEffect::All;
 
+  if (info.isNoReturn())
+    attrs.set(cir::CIRDialect::getNoReturnAttrName(),
+              mlir::UnitAttr::get(&getMLIRContext()));
+  // TODO(cir): Check/add cmse_nonsecure_call attribute here.
+
   addAttributesFromFunctionProtoType(getBuilder(), attrs,
                                      calleeInfo.getCalleeFunctionProtoType());
 
@@ -129,11 +136,30 @@ void CIRGenModule::constructAttributeList(llvm::StringRef 
name,
     if (targetDecl->hasAttr<NoThrowAttr>())
       attrs.set(cir::CIRDialect::getNoThrowAttrName(),
                 mlir::UnitAttr::get(&getMLIRContext()));
+    // TODO(cir): This is actually only possible if targetDecl isn't a
+    // declarator, which ObjCMethodDecl seems to be the only way to get this to
+    // happen.  We're including it here for completeness, but we should add a
+    // test for this when we start generating ObjectiveC.
+    if (targetDecl->hasAttr<NoReturnAttr>())
+      attrs.set(cir::CIRDialect::getNoReturnAttrName(),
+                mlir::UnitAttr::get(&getMLIRContext()));
 
     if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
       addAttributesFromFunctionProtoType(
           getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
       assert(!cir::MissingFeatures::opCallAttrs());
+
+      const CXXMethodDecl *md = dyn_cast<CXXMethodDecl>(func);
+      bool isVirtualCall = md && md->isVirtual();
+
+      // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
+      // virtual function. These attributes are not inherited by overloads.
+      if (!(attrOnCallSite && isVirtualCall)) {
+        if (func->isNoReturn())
+          attrs.set(cir::CIRDialect::getNoReturnAttrName(),
+                    mlir::UnitAttr::get(&getMLIRContext()));
+        // TODO(cir): Set NoBuiltinAttr here.
+      }
     }
 
     assert(!cir::MissingFeatures::opCallAttrs());
@@ -222,7 +248,8 @@ CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
 
-  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+  return arrangeCIRFunctionInfo(fpt->getExtInfo(), resultType, argTypes,
+                                required);
 }
 
 /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
@@ -259,7 +286,8 @@ arrangeCIRFunctionInfo(CIRGenTypes &cgt, 
SmallVectorImpl<CanQualType> &prefix,
   assert(!cir::MissingFeatures::opCallExtParameterInfo());
   appendParameterTypes(cgt, prefix, fpt);
   CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
-  return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
+  return cgt.arrangeCIRFunctionInfo(fpt->getExtInfo(), resultType, prefix,
+                                    required);
 }
 
 void CIRGenFunction::emitDelegateCallArg(CallArgList &args,
@@ -325,7 +353,8 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   CanQualType retType = fnType->getReturnType()->getCanonicalTypeUnqualified();
 
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
-  return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
+  return cgt.arrangeCIRFunctionInfo(fnType->getExtInfo(), retType, argTypes,
+                                    required);
 }
 
 /// Arrange a call to a C++ method, passing the given arguments.
@@ -364,7 +393,8 @@ const CIRGenFunctionInfo 
&CIRGenTypes::arrangeCXXConstructorCall(
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
 
-  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+  return arrangeCIRFunctionInfo(fpt->getExtInfo(), resultType, argTypes,
+                                required);
 }
 
 /// Arrange a call to a C++ method, passing the given arguments.
@@ -385,6 +415,7 @@ const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXMethodCall(
 
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
   return arrangeCIRFunctionInfo(
+      proto->getExtInfo(),
       proto->getReturnType()->getCanonicalTypeUnqualified(), argTypes,
       required);
 }
@@ -456,8 +487,8 @@ CIRGenTypes::arrangeFunctionDeclaration(const FunctionDecl 
*fd) {
           funcTy.getAs<FunctionNoProtoType>()) {
     assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
     assert(!cir::MissingFeatures::opCallFnInfoOpts());
-    return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
-                                  RequiredArgs::All);
+    return arrangeCIRFunctionInfo(
+        noProto->getExtInfo(), noProto->getReturnType(), {}, 
RequiredArgs::All);
   }
 
   return arrangeFreeFunctionType(funcTy.castAs<FunctionProtoType>());
@@ -535,7 +566,8 @@ const CIRGenFunctionInfo &
 CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {
   CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
-  return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
+  return arrangeCIRFunctionInfo(fnpt->getExtInfo(), resultType, {},
+                                RequiredArgs(0));
 }
 
 RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h 
b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
index 4f5754cb43986..fb7da9e414139 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -72,6 +72,10 @@ class RequiredArgs {
 class CIRGenFunctionInfo final
     : public llvm::FoldingSetNode,
       private llvm::TrailingObjects<CIRGenFunctionInfo, CanQualType> {
+  // Whether this function has noreturn.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned noReturn : 1;
+
   RequiredArgs required;
 
   unsigned numArgs;
@@ -81,8 +85,19 @@ class CIRGenFunctionInfo final
 
   CIRGenFunctionInfo() : required(RequiredArgs::All) {}
 
+  FunctionType::ExtInfo getExtInfo() const {
+    // TODO(cir): as we add this information to this type, we need to add calls
+    // here instead of explicit false/0.
+    return FunctionType::ExtInfo(
+        isNoReturn(), /*getHasRegParm=*/false, /*getRegParm=*/false,
+        /*getASTCallingConvention=*/CallingConv(0), 
/*isReturnsRetained=*/false,
+        /*isNoCallerSavedRegs=*/false, /*isNoCfCheck=*/false,
+        /*isCmseNSCall=*/false);
+  }
+
 public:
-  static CIRGenFunctionInfo *create(CanQualType resultType,
+  static CIRGenFunctionInfo *create(FunctionType::ExtInfo info,
+                                    CanQualType resultType,
                                     llvm::ArrayRef<CanQualType> argTypes,
                                     RequiredArgs required);
 
@@ -97,9 +112,10 @@ class CIRGenFunctionInfo final
 
   // This function has to be CamelCase because llvm::FoldingSet requires so.
   // NOLINTNEXTLINE(readability-identifier-naming)
-  static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required,
-                      CanQualType resultType,
+  static void Profile(llvm::FoldingSetNodeID &id, FunctionType::ExtInfo info,
+                      RequiredArgs required, CanQualType resultType,
                       llvm::ArrayRef<CanQualType> argTypes) {
+    id.AddBoolean(info.getNoReturn());
     id.AddBoolean(required.getOpaqueData());
     resultType.Profile(id);
     for (const CanQualType &arg : argTypes)
@@ -111,7 +127,7 @@ class CIRGenFunctionInfo final
     // If the Profile functions get out of sync, we can end up with incorrect
     // function signatures, so we call the static Profile function here rather
     // than duplicating the logic.
-    Profile(id, required, getReturnType(), arguments());
+    Profile(id, getExtInfo(), required, getReturnType(), arguments());
   }
 
   llvm::ArrayRef<CanQualType> arguments() const {
@@ -144,6 +160,8 @@ class CIRGenFunctionInfo final
     return isVariadic() ? getRequiredArgs().getNumRequiredArgs()
                         : argTypeSize();
   }
+
+  bool isNoReturn() const { return noReturn; }
 };
 
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 610ee2ceb1da4..1b0aad37569c4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -662,15 +662,14 @@ bool CIRGenTypes::isZeroInitializable(const RecordDecl 
*rd) {
   return getCIRGenRecordLayout(rd).isZeroInitializable();
 }
 
-const CIRGenFunctionInfo &
-CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType,
-                                    llvm::ArrayRef<CanQualType> argTypes,
-                                    RequiredArgs required) {
+const CIRGenFunctionInfo &CIRGenTypes::arrangeCIRFunctionInfo(
+    FunctionType::ExtInfo info, CanQualType returnType,
+    llvm::ArrayRef<CanQualType> argTypes, RequiredArgs required) {
   assert(llvm::all_of(argTypes,
                       [](CanQualType t) { return t.isCanonicalAsParam(); }));
   // Lookup or create unique function info.
   llvm::FoldingSetNodeID id;
-  CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
+  CIRGenFunctionInfo::Profile(id, info, required, returnType, argTypes);
 
   void *insertPos = nullptr;
   CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
@@ -687,7 +686,7 @@ CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType,
   assert(!cir::MissingFeatures::opCallCallConv());
 
   // Construction the function info. We co-allocate the ArgInfos.
-  fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
+  fi = CIRGenFunctionInfo::create(info, returnType, argTypes, required);
   functionInfos.InsertNode(fi, insertPos);
 
   return *fi;
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h 
b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index e79cdfc9f8224..bbc594c8656da 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -197,7 +197,7 @@ class CIRGenTypes {
                                                     const FunctionType 
*fnType);
 
   const CIRGenFunctionInfo &
-  arrangeCIRFunctionInfo(CanQualType returnType,
+  arrangeCIRFunctionInfo(FunctionType::ExtInfo info, CanQualType returnType,
                          llvm::ArrayRef<CanQualType> argTypes,
                          RequiredArgs required);
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4877508b1c3da..20bfb6c3153e1 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -310,7 +310,8 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
 void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow,
                               cir::SideEffect sideEffect,
                               mlir::LLVM::MemoryEffectsAttr &memoryEffect,
-                              bool &noUnwind, bool &willReturn) {
+                              bool &noUnwind, bool &willReturn,
+                              bool &noReturn) {
   using mlir::LLVM::ModRefInfo;
 
   switch (sideEffect) {
@@ -344,6 +345,8 @@ void convertSideEffectForCall(mlir::Operation *callOp, bool 
isNothrow,
     willReturn = true;
     break;
   }
+
+  noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
 }
 
 static mlir::LLVM::CallIntrinsicOp
@@ -1620,8 +1623,9 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange 
callOperands,
   mlir::LLVM::MemoryEffectsAttr memoryEffects;
   bool noUnwind = false;
   bool willReturn = false;
+  bool noReturn = false;
   convertSideEffectForCall(op, call.getNothrow(), call.getSideEffect(),
-                           memoryEffects, noUnwind, willReturn);
+                           memoryEffects, noUnwind, willReturn, noReturn);
 
   mlir::LLVM::LLVMFunctionType llvmFnTy;
 
@@ -1684,6 +1688,7 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange 
callOperands,
     newOp.setMemoryEffectsAttr(memoryEffects);
   newOp.setNoUnwind(noUnwind);
   newOp.setWillReturn(willReturn);
+  newOp.setNoReturn(noReturn);
 
   return mlir::success();
 }
@@ -2036,6 +2041,7 @@ void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
         attr.getName() == func.getDsoLocalAttrName() ||
         attr.getName() == func.getInlineKindAttrName() ||
         attr.getName() == func.getSideEffectAttrName() ||
+        attr.getName() == CIRDialect::getNoReturnAttrName() ||
         (filterArgAndResAttrs &&
          (attr.getName() == func.getArgAttrsAttrName() ||
           attr.getName() == func.getResAttrsAttrName())))
@@ -2151,6 +2157,9 @@ mlir::LogicalResult 
CIRToLLVMFuncOpLowering::matchAndRewrite(
     }
   }
 
+  if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
+    fn.setNoReturn(true);
+
   if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
     fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
     fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
diff --git a/clang/test/CIR/CodeGen/noreturn.cpp 
b/clang/test/CIR/CodeGen/noreturn.cpp
new file mode 100644
index 0000000000000..ddb9e25802ddb
--- /dev/null
+++ b/clang/test/CIR/CodeGen/noreturn.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+extern "C" {
+// CIR: cir.func {{.*}} @bar() -> !s32i attributes {no_return} {
+// LLVM: Function Attrs:{{.*}} noreturn
+// LLVM-NEXT: define {{.*}} i32 @bar() #[[BAR_FOO_ATTR:.*]] {
+// OGCG: Function Attrs:{{.*}} noreturn
+// OGCG-NEXT: define {{.*}} i32 @bar() #[[BAR_FOO_ATTR:.*]] {
+__attribute((noreturn))
+int bar() { }
+
+// Note: Classic codegen puts this here, so we need this to make sure the
+// FunctionAttrs from `trap` doesn't interfere with 'foo'. However, CIR->LLVM
+// lowering puts the trap decl at the end, so it isn't here to worry about.
+// OGCG: declare void @llvm.trap
+
+// CIR: cir.func {{.*}} @foo() -> !s32i attributes {no_return} {
+// LLVM: Function Attrs:{{.*}} noreturn
+// LLVM-NEXT: define {{.*}} i32 @foo() #[[BAR_FOO_ATTR:.*]] {
+// OGCG: Function Attrs:{{.*}} noreturn
+// OGCG-NEXT: define {{.*}} i32 @foo() #[[BAR_FOO_ATTR:.*]] {
+[[noreturn]]
+int foo() { }
+
+void caller() {
+  // CIR: cir.call @bar() {no_return} : () -> !s32i
+  // LLVM: call i32 @bar() #[[CALL_ATTR:.*]]
+  // OGCG: call i32 @bar() #[[CALL_ATTR:.*]]
+  bar();
+}
+
+void caller2() {
+  // CIR: cir.call @foo() {no_return} : () -> !s32i
+  // LLVM: call i32 @foo() #[[CALL_ATTR:.*]]
+  // OGCG: call i32 @foo() #[[CALL_ATTR:.*]]
+  foo();
+}
+
+// LLVM: attributes #[[BAR_FOO_ATTR]] = {{.*}}noreturn
+// OGCG: attributes #[[BAR_FOO_ATTR]] = {{.*}}noreturn
+// LLVM: attributes #[[CALL_ATTR]] = {{.*}}noreturn
+// OGCG: attributes #[[CALL_ATTR]] = {{.*}}noreturn
+
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp
index a08a784951247..fc9e89b0ac486 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp
@@ -85,7 +85,7 @@ 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>) -> !s32i
-// CIR: cir.call @abort() nothrow : () -> ()
+// CIR: cir.call @abort() nothrow {no_return} : () -> ()
 
 // LLVM: define{{.*}} void @_Z16library_builtinsv()
 // LLVM: call i32 (ptr, ...) @printf(ptr null)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 6789ca22c3d5f..b8b31680df824 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -795,6 +795,7 @@ def LLVM_CallOp
       DefaultValuedAttr<TailCallKind, "TailCallKind::None">:$TailCallKind,
       OptionalAttr<LLVM_MemoryEffectsAttr>:$memory_effects,
       UnitAttr:$convergent, UnitAttr:$no_unwind, UnitAttr:$will_return,
+      UnitAttr:$no_return,
       VariadicOfVariadic<LLVM_Type, "op_bundle_sizes">:$op_bundle_operands,
       DenseI32ArrayAttr:$op_bundle_sizes,
       OptionalAttr<ArrayAttr>:$op_bundle_tags,
@@ -1992,6 +1993,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
     OptionalAttr<UnitAttr>:$inline_hint,
     OptionalAttr<UnitAttr>:$no_unwind,
     OptionalAttr<UnitAttr>:$will_return,
+    OptionalAttr<UnitAttr>:$no_return,
     OptionalAttr<UnitAttr>:$optimize_none,
     OptionalAttr<LLVM_VecTypeHintAttr>:$vec_type_hint,
     OptionalAttr<DenseI32ArrayAttr>:$work_group_size_hint,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp 
b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 91fbc53c5eb32..e0b751fc55664 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -995,6 +995,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state, TypeRange results,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr,
         /*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
+        /*no_return=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1025,6 +1026,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state,
         /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
         /*convergent=*/nullptr,
         /*no_unwind=*/nullptr, /*will_return=*/nullptr,
+        /*no_return=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr,
@@ -1041,6 +1043,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state,
         /*fastmathFlags=*/nullptr,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr, 
/*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
+        /*no_return=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1057,6 +1060,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state, LLVMFuncOp func,
         /*fastmathFlags=*/nullptr,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr, 
/*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
+        /*no_return=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp 
b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index b6ea4ba6e4921..1f53cfe8ece27 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -421,6 +421,8 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase 
&builder,
       call->addFnAttr(llvm::Attribute::NoUnwind);
     if (callOp.getWillReturnAttr())
       call->addFnAttr(llvm::Attribute::WillReturn);
+    if (callOp.getNoReturnAttr())
+      call->addFnAttr(llvm::Attribute::NoReturn);
     if (callOp.getNoInlineAttr())
       call->addFnAttr(llvm::Attribute::NoInline);
     if (callOp.getAlwaysInlineAttr())
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp 
b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index cec968c02078d..dca3a36133748 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2673,6 +2673,7 @@ static constexpr std::array kExplicitLLVMFuncOpAttributes{
     StringLiteral("uwtable"),
     StringLiteral("vscale_range"),
     StringLiteral("willreturn"),
+    StringLiteral("noreturn"),
 };
 
 /// Converts LLVM attributes from `func` into MLIR attributes and adds them
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index fad9bd6b78018..50beb1a2ec410 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1676,6 +1676,8 @@ static void convertFunctionAttributes(LLVMFuncOp func,
     llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
   if (func.getWillReturnAttr())
     llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
+  if (func.getNoReturnAttr())
+    llvmFunc->addFnAttr(llvm::Attribute::NoReturn);
   if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
     llvmFunc->addFnAttr("target-features", targetFeatAttr.getFeaturesString());
   if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())

>From 792d348d741d4b89b497d1ab735599d4c7362a01 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Mon, 26 Jan 2026 08:19:36 -0800
Subject: [PATCH 2/4] Add requested MLIR tests, fixup all the missing import
 functionality

---
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       |  5 +++-
 mlir/test/Dialect/LLVMIR/func.mlir            |  5 ++++
 mlir/test/Dialect/LLVMIR/roundtrip.mlir       |  3 +++
 .../LLVMIR/Import/function-attributes.ll      |  6 +++++
 .../test/Target/LLVMIR/Import/instructions.ll | 12 +++++++++
 mlir/test/Target/LLVMIR/llvmir.mlir           | 25 +++++++++++++++++++
 6 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp 
b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index dca3a36133748..78338f597b420 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2666,6 +2666,7 @@ static constexpr std::array kExplicitLLVMFuncOpAttributes{
     StringLiteral("no-nans-fp-math"),
     StringLiteral("no-signed-zeros-fp-math"),
     StringLiteral("noinline"),
+    StringLiteral("noreturn"),
     StringLiteral("nounwind"),
     StringLiteral("optnone"),
     StringLiteral("target-features"),
@@ -2673,7 +2674,6 @@ static constexpr std::array kExplicitLLVMFuncOpAttributes{
     StringLiteral("uwtable"),
     StringLiteral("vscale_range"),
     StringLiteral("willreturn"),
-    StringLiteral("noreturn"),
 };
 
 /// Converts LLVM attributes from `func` into MLIR attributes and adds them
@@ -2708,6 +2708,8 @@ void 
ModuleImport::processFunctionAttributes(llvm::Function *func,
     funcOp.setNoUnwind(true);
   if (func->hasFnAttribute(llvm::Attribute::WillReturn))
     funcOp.setWillReturn(true);
+  if (func->hasFnAttribute(llvm::Attribute::NoReturn))
+    funcOp.setNoReturn(true);
 
   if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
     funcOp.setArmStreaming(true);
@@ -2928,6 +2930,7 @@ LogicalResult 
ModuleImport::convertCallAttributes(llvm::CallInst *inst,
   op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
   op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
   op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
+  op.setNoReturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
   op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
   op.setAlwaysInline(
       callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir 
b/mlir/test/Dialect/LLVMIR/func.mlir
index 094313ca048c7..09f481a9f908c 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -324,6 +324,11 @@ module {
     llvm.return
   }
 
+  llvm.func @noreturn_function() attributes {no_return} {
+    // CHECK: @noreturn_function
+    // CHECK-SAME: attributes {no_return}
+    llvm.return
+  }
 
 }
 
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir 
b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index afbf47ef3041d..42e64835d6b7b 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -122,6 +122,9 @@ func.func @ops(%arg0: i32, %arg1: f32,
 // CHECK: llvm.call @baz() {will_return} : () -> ()
   llvm.call @baz() {will_return} : () -> ()
 
+// CHECK: llvm.call @baz() {noreturn} : () -> ()
+  llvm.call @baz() {no_return} : () -> ()
+
 // CHECK: llvm.call @baz() {memory = #llvm.memory_effects<other = none, argMem 
= read, inaccessibleMem = write, errnoMem = none, targetMem0 = none, targetMem1 
= none>} : () -> ()
   llvm.call @baz() {memory = #llvm.memory_effects<other = none, argMem = read, 
inaccessibleMem = write, errnoMem = none, targetMem0 = none, targetMem1 = 
none>} : () -> ()
 
diff --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll 
b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
index 023b0120f9bbe..61b5caabdc0e4 100644
--- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
@@ -411,5 +411,11 @@ declare void @willreturn_attribute() willreturn
 
 // -----
 
+; CHECK-LABEL: @noreturn_attribute
+; CHECK-SAME: attributes {no_return}
+declare void @noreturn_attribute() noreturn
+
+// -----
+
 ; expected-warning @unknown {{'preallocated' attribute is invalid on current 
operation, skipping it}}
 declare void @test() preallocated(i32)
diff --git a/mlir/test/Target/LLVMIR/Import/instructions.ll 
b/mlir/test/Target/LLVMIR/Import/instructions.ll
index 7f9c511ec75b0..c7efd69b8ff13 100644
--- a/mlir/test/Target/LLVMIR/Import/instructions.ll
+++ b/mlir/test/Target/LLVMIR/Import/instructions.ll
@@ -701,6 +701,18 @@ define void @call_will_return() {
 ; CHECK: llvm.func @f()
 declare void @f()
 
+; CHECK-LABEL: @call_noreturn
+define void @call_noreturn() {
+; CHECK: llvm.call @f() {no_return}
+  call void @f() noreturn
+  ret void
+}
+
+; // -----
+
+; CHECK: llvm.func @f()
+declare void @f()
+
 ; CHECK-LABEL: @call_memory_effects
 define void @call_memory_effects() {
 ; CHECK: llvm.call @f() {memory_effects = #llvm.memory_effects<other = none, 
argMem = none, inaccessibleMem = none, errnoMem = none, targetMem0 = none, 
targetMem1 = none>}
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir 
b/mlir/test/Target/LLVMIR/llvmir.mlir
index 819a514bc8b7e..1f1110af51c83 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2631,6 +2631,17 @@ llvm.func @willreturn() attributes { will_return } {
 
 // -----
 
+// CHECK-LABEL: @noreturn
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @noreturn() attributes { no_return } {
+  llvm.return
+}
+
+// CHECK: #[[ATTRS]]
+// CHECK-SAME: noreturn
+
+// -----
+
 llvm.func @f()
 
 // CHECK-LABEL: @convergent_call
@@ -2675,6 +2686,20 @@ llvm.func @willreturn_call() {
 
 llvm.func @f()
 
+// CHECK-LABEL: @noreturn_call
+// CHECK: call void @f() #[[ATTRS:[0-9]+]]
+llvm.func @noreturn_call() {
+  llvm.call @f() {no_return} : () -> ()
+  llvm.return
+}
+
+// CHECK: #[[ATTRS]]
+// CHECK-SAME: noreturn
+
+// -----
+
+llvm.func @f()
+
 // CHECK-LABEL: @no_inline_call
 // CHECK: call void @f() #[[ATTRS:[0-9]+]]
 llvm.func @no_inline_call() {

>From 0f6d45e10e9c13fdcc491864b5d1f1e23dc0f05c Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Mon, 26 Jan 2026 09:53:56 -0800
Subject: [PATCH 3/4] Remove duplicate OGCG lines, we can split them back out
 in the future if these diverge in any reasonable way

---
 clang/test/CIR/CodeGen/noreturn.cpp | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/clang/test/CIR/CodeGen/noreturn.cpp 
b/clang/test/CIR/CodeGen/noreturn.cpp
index ddb9e25802ddb..ef85622a83f6c 100644
--- a/clang/test/CIR/CodeGen/noreturn.cpp
+++ b/clang/test/CIR/CodeGen/noreturn.cpp
@@ -3,14 +3,12 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll
 // RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+// RUN: FileCheck --input-file=%t.ll %s -check-prefixes=LLVM,OGCG
 
 extern "C" {
 // CIR: cir.func {{.*}} @bar() -> !s32i attributes {no_return} {
 // LLVM: Function Attrs:{{.*}} noreturn
 // LLVM-NEXT: define {{.*}} i32 @bar() #[[BAR_FOO_ATTR:.*]] {
-// OGCG: Function Attrs:{{.*}} noreturn
-// OGCG-NEXT: define {{.*}} i32 @bar() #[[BAR_FOO_ATTR:.*]] {
 __attribute((noreturn))
 int bar() { }
 
@@ -21,29 +19,23 @@ int bar() { }
 
 // CIR: cir.func {{.*}} @foo() -> !s32i attributes {no_return} {
 // LLVM: Function Attrs:{{.*}} noreturn
-// LLVM-NEXT: define {{.*}} i32 @foo() #[[BAR_FOO_ATTR:.*]] {
-// OGCG: Function Attrs:{{.*}} noreturn
-// OGCG-NEXT: define {{.*}} i32 @foo() #[[BAR_FOO_ATTR:.*]] {
+// LLVM-NEXT: define {{.*}} i32 @foo() #[[BAR_FOO_ATTR]] {
 [[noreturn]]
 int foo() { }
 
 void caller() {
   // CIR: cir.call @bar() {no_return} : () -> !s32i
   // LLVM: call i32 @bar() #[[CALL_ATTR:.*]]
-  // OGCG: call i32 @bar() #[[CALL_ATTR:.*]]
   bar();
 }
 
 void caller2() {
   // CIR: cir.call @foo() {no_return} : () -> !s32i
-  // LLVM: call i32 @foo() #[[CALL_ATTR:.*]]
-  // OGCG: call i32 @foo() #[[CALL_ATTR:.*]]
+  // LLVM: call i32 @foo() #[[CALL_ATTR]]
   foo();
 }
 
 // LLVM: attributes #[[BAR_FOO_ATTR]] = {{.*}}noreturn
-// OGCG: attributes #[[BAR_FOO_ATTR]] = {{.*}}noreturn
 // LLVM: attributes #[[CALL_ATTR]] = {{.*}}noreturn
-// OGCG: attributes #[[CALL_ATTR]] = {{.*}}noreturn
 
 }

>From 60fcfcbf0be58d4742c22e3949ceebb16beab0f4 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Mon, 26 Jan 2026 16:35:51 -0800
Subject: [PATCH 4/4] Switch everything to Please ask your administrator.
 spelling, rather than LLVM-IR dialect being different

---
 clang/include/clang/CIR/Dialect/IR/CIRDialect.td          | 2 +-
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp       | 4 ++--
 clang/test/CIR/CodeGen/noreturn.cpp                       | 8 ++++----
 clang/test/CIR/CodeGenBuiltins/builtin_call.cpp           | 2 +-
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td               | 4 ++--
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp                | 8 ++++----
 .../LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp     | 2 +-
 mlir/lib/Target/LLVMIR/ModuleImport.cpp                   | 4 ++--
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp              | 2 +-
 mlir/test/Dialect/LLVMIR/func.mlir                        | 4 ++--
 mlir/test/Dialect/LLVMIR/roundtrip.mlir                   | 2 +-
 mlir/test/Target/LLVMIR/Import/function-attributes.ll     | 2 +-
 mlir/test/Target/LLVMIR/Import/instructions.ll            | 2 +-
 mlir/test/Target/LLVMIR/llvmir.mlir                       | 4 ++--
 14 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 058f096bfae3b..47ca625c34816 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -39,7 +39,7 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
     static llvm::StringRef getCalleeAttrName() { return "callee"; }
     static llvm::StringRef getNoThrowAttrName() { return "nothrow"; }
-    static llvm::StringRef getNoReturnAttrName() { return "no_return"; }
+    static llvm::StringRef getNoReturnAttrName() { return "noreturn"; }
     static llvm::StringRef getSideEffectAttrName() { return "side_effect"; }
     static llvm::StringRef getModuleLevelAsmAttrName() { return 
"cir.module_asm"; }
     static llvm::StringRef getGlobalCtorsAttrName() { return 
"cir.global_ctors"; }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 20bfb6c3153e1..86c780e0e9c40 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1688,7 +1688,7 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange 
callOperands,
     newOp.setMemoryEffectsAttr(memoryEffects);
   newOp.setNoUnwind(noUnwind);
   newOp.setWillReturn(willReturn);
-  newOp.setNoReturn(noReturn);
+  newOp.setNoreturn(noReturn);
 
   return mlir::success();
 }
@@ -2158,7 +2158,7 @@ mlir::LogicalResult 
CIRToLLVMFuncOpLowering::matchAndRewrite(
   }
 
   if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
-    fn.setNoReturn(true);
+    fn.setNoreturn(true);
 
   if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
     fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
diff --git a/clang/test/CIR/CodeGen/noreturn.cpp 
b/clang/test/CIR/CodeGen/noreturn.cpp
index ef85622a83f6c..840f883062e7c 100644
--- a/clang/test/CIR/CodeGen/noreturn.cpp
+++ b/clang/test/CIR/CodeGen/noreturn.cpp
@@ -6,7 +6,7 @@
 // RUN: FileCheck --input-file=%t.ll %s -check-prefixes=LLVM,OGCG
 
 extern "C" {
-// CIR: cir.func {{.*}} @bar() -> !s32i attributes {no_return} {
+// CIR: cir.func {{.*}} @bar() -> !s32i attributes {noreturn} {
 // LLVM: Function Attrs:{{.*}} noreturn
 // LLVM-NEXT: define {{.*}} i32 @bar() #[[BAR_FOO_ATTR:.*]] {
 __attribute((noreturn))
@@ -17,20 +17,20 @@ int bar() { }
 // lowering puts the trap decl at the end, so it isn't here to worry about.
 // OGCG: declare void @llvm.trap
 
-// CIR: cir.func {{.*}} @foo() -> !s32i attributes {no_return} {
+// CIR: cir.func {{.*}} @foo() -> !s32i attributes {noreturn} {
 // LLVM: Function Attrs:{{.*}} noreturn
 // LLVM-NEXT: define {{.*}} i32 @foo() #[[BAR_FOO_ATTR]] {
 [[noreturn]]
 int foo() { }
 
 void caller() {
-  // CIR: cir.call @bar() {no_return} : () -> !s32i
+  // CIR: cir.call @bar() {noreturn} : () -> !s32i
   // LLVM: call i32 @bar() #[[CALL_ATTR:.*]]
   bar();
 }
 
 void caller2() {
-  // CIR: cir.call @foo() {no_return} : () -> !s32i
+  // CIR: cir.call @foo() {noreturn} : () -> !s32i
   // LLVM: call i32 @foo() #[[CALL_ATTR]]
   foo();
 }
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp
index fc9e89b0ac486..8ca7762257cf3 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin_call.cpp
@@ -85,7 +85,7 @@ 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>) -> !s32i
-// CIR: cir.call @abort() nothrow {no_return} : () -> ()
+// CIR: cir.call @abort() nothrow {noreturn} : () -> ()
 
 // LLVM: define{{.*}} void @_Z16library_builtinsv()
 // LLVM: call i32 (ptr, ...) @printf(ptr null)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index b8b31680df824..390d5a1ea7dfe 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -795,7 +795,7 @@ def LLVM_CallOp
       DefaultValuedAttr<TailCallKind, "TailCallKind::None">:$TailCallKind,
       OptionalAttr<LLVM_MemoryEffectsAttr>:$memory_effects,
       UnitAttr:$convergent, UnitAttr:$no_unwind, UnitAttr:$will_return,
-      UnitAttr:$no_return,
+      UnitAttr:$noreturn,
       VariadicOfVariadic<LLVM_Type, "op_bundle_sizes">:$op_bundle_operands,
       DenseI32ArrayAttr:$op_bundle_sizes,
       OptionalAttr<ArrayAttr>:$op_bundle_tags,
@@ -1993,7 +1993,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
     OptionalAttr<UnitAttr>:$inline_hint,
     OptionalAttr<UnitAttr>:$no_unwind,
     OptionalAttr<UnitAttr>:$will_return,
-    OptionalAttr<UnitAttr>:$no_return,
+    OptionalAttr<UnitAttr>:$noreturn,
     OptionalAttr<UnitAttr>:$optimize_none,
     OptionalAttr<LLVM_VecTypeHintAttr>:$vec_type_hint,
     OptionalAttr<DenseI32ArrayAttr>:$work_group_size_hint,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp 
b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index e0b751fc55664..d1c45bcb1656b 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -995,7 +995,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state, TypeRange results,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr,
         /*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
-        /*no_return=*/nullptr,
+        /*noreturn=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1026,7 +1026,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state,
         /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
         /*convergent=*/nullptr,
         /*no_unwind=*/nullptr, /*will_return=*/nullptr,
-        /*no_return=*/nullptr,
+        /*noreturn=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr,
@@ -1043,7 +1043,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state,
         /*fastmathFlags=*/nullptr,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr, 
/*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
-        /*no_return=*/nullptr,
+        /*noreturn=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1060,7 +1060,7 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state, LLVMFuncOp func,
         /*fastmathFlags=*/nullptr,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr, 
/*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
-        /*no_return=*/nullptr,
+        /*noreturn=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp 
b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 1f53cfe8ece27..b1d7f3ab7b777 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -421,7 +421,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase 
&builder,
       call->addFnAttr(llvm::Attribute::NoUnwind);
     if (callOp.getWillReturnAttr())
       call->addFnAttr(llvm::Attribute::WillReturn);
-    if (callOp.getNoReturnAttr())
+    if (callOp.getNoreturnAttr())
       call->addFnAttr(llvm::Attribute::NoReturn);
     if (callOp.getNoInlineAttr())
       call->addFnAttr(llvm::Attribute::NoInline);
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp 
b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 78338f597b420..555e72bd77358 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2709,7 +2709,7 @@ void 
ModuleImport::processFunctionAttributes(llvm::Function *func,
   if (func->hasFnAttribute(llvm::Attribute::WillReturn))
     funcOp.setWillReturn(true);
   if (func->hasFnAttribute(llvm::Attribute::NoReturn))
-    funcOp.setNoReturn(true);
+    funcOp.setNoreturn(true);
 
   if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
     funcOp.setArmStreaming(true);
@@ -2930,7 +2930,7 @@ LogicalResult 
ModuleImport::convertCallAttributes(llvm::CallInst *inst,
   op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
   op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
   op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
-  op.setNoReturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
+  op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
   op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
   op.setAlwaysInline(
       callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 50beb1a2ec410..46a0b97f1edbd 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1676,7 +1676,7 @@ static void convertFunctionAttributes(LLVMFuncOp func,
     llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
   if (func.getWillReturnAttr())
     llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
-  if (func.getNoReturnAttr())
+  if (func.getNoreturnAttr())
     llvmFunc->addFnAttr(llvm::Attribute::NoReturn);
   if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
     llvmFunc->addFnAttr("target-features", targetFeatAttr.getFeaturesString());
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir 
b/mlir/test/Dialect/LLVMIR/func.mlir
index 09f481a9f908c..936260f862a98 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -324,9 +324,9 @@ module {
     llvm.return
   }
 
-  llvm.func @noreturn_function() attributes {no_return} {
+  llvm.func @noreturn_function() attributes {noreturn} {
     // CHECK: @noreturn_function
-    // CHECK-SAME: attributes {no_return}
+    // CHECK-SAME: attributes {noreturn}
     llvm.return
   }
 
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir 
b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 42e64835d6b7b..fc2456b350a56 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -123,7 +123,7 @@ func.func @ops(%arg0: i32, %arg1: f32,
   llvm.call @baz() {will_return} : () -> ()
 
 // CHECK: llvm.call @baz() {noreturn} : () -> ()
-  llvm.call @baz() {no_return} : () -> ()
+  llvm.call @baz() {noreturn} : () -> ()
 
 // CHECK: llvm.call @baz() {memory = #llvm.memory_effects<other = none, argMem 
= read, inaccessibleMem = write, errnoMem = none, targetMem0 = none, targetMem1 
= none>} : () -> ()
   llvm.call @baz() {memory = #llvm.memory_effects<other = none, argMem = read, 
inaccessibleMem = write, errnoMem = none, targetMem0 = none, targetMem1 = 
none>} : () -> ()
diff --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll 
b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
index 61b5caabdc0e4..69e18e1c5bbff 100644
--- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
@@ -412,7 +412,7 @@ declare void @willreturn_attribute() willreturn
 // -----
 
 ; CHECK-LABEL: @noreturn_attribute
-; CHECK-SAME: attributes {no_return}
+; CHECK-SAME: attributes {noreturn}
 declare void @noreturn_attribute() noreturn
 
 // -----
diff --git a/mlir/test/Target/LLVMIR/Import/instructions.ll 
b/mlir/test/Target/LLVMIR/Import/instructions.ll
index c7efd69b8ff13..766f19ce386f8 100644
--- a/mlir/test/Target/LLVMIR/Import/instructions.ll
+++ b/mlir/test/Target/LLVMIR/Import/instructions.ll
@@ -703,7 +703,7 @@ declare void @f()
 
 ; CHECK-LABEL: @call_noreturn
 define void @call_noreturn() {
-; CHECK: llvm.call @f() {no_return}
+; CHECK: llvm.call @f() {noreturn}
   call void @f() noreturn
   ret void
 }
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir 
b/mlir/test/Target/LLVMIR/llvmir.mlir
index 1f1110af51c83..12d73b429b3ce 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2633,7 +2633,7 @@ llvm.func @willreturn() attributes { will_return } {
 
 // CHECK-LABEL: @noreturn
 // CHECK-SAME: #[[ATTRS:[0-9]+]]
-llvm.func @noreturn() attributes { no_return } {
+llvm.func @noreturn() attributes { noreturn } {
   llvm.return
 }
 
@@ -2689,7 +2689,7 @@ llvm.func @f()
 // CHECK-LABEL: @noreturn_call
 // CHECK: call void @f() #[[ATTRS:[0-9]+]]
 llvm.func @noreturn_call() {
-  llvm.call @f() {no_return} : () -> ()
+  llvm.call @f() {noreturn} : () -> ()
   llvm.return
 }
 

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

Reply via email to