[clang] [mlir] [CIR] Implement 'noreturn' attribute for functions/calls. (PR #177978)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 26 07:34:44 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
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.
---
Patch is 22.42 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/177978.diff
13 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.td (+1)
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+40-8)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h (+22-4)
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+5-6)
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+1-1)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+11-2)
- (added) clang/test/CIR/CodeGen/noreturn.cpp (+49)
- (modified) clang/test/CIR/CodeGenBuiltins/builtin_call.cpp (+1-1)
- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td (+2)
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp (+4)
- (modified) mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp (+2)
- (modified) mlir/lib/Target/LLVMIR/ModuleImport.cpp (+1)
- (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+2)
``````````diff
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,
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/177978
More information about the cfe-commits
mailing list