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
