[clang] [mlir] [CIR] 3 more 'quick' function attribute lowering through LLVMIRDialect (PR #178443)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 28 07:17:16 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
This patch lowers 3 more attributes, two of which are trivial, and one which has a touch of a complication.
The two trivial ones are no_caller_saved_registers and nocallback, which are language-level attributes that are effectively just passed on.
The final one is a touch more complicated, as it is a 'string' attribute: modular-format. Also, it has a dash in the LLVM-IR version, but that isn't possible to add as a name in the LLVM-IR MLIR Dialect (see the comment inline). It also has a string of some consequence (that is checked in LLVM), but that is just passed to LLVM directly.
---
Patch is 22.13 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/178443.diff
13 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.td (+9)
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+52-8)
- (modified) clang/test/CIR/CodeGen/misc-attrs.cpp (+40)
- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td (+5)
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp (+4)
- (modified) mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp (+9)
- (modified) mlir/lib/Target/LLVMIR/ModuleImport.cpp (+17)
- (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+6)
- (modified) mlir/test/Dialect/LLVMIR/func.mlir (+19)
- (modified) mlir/test/Dialect/LLVMIR/roundtrip.mlir (+9)
- (modified) mlir/test/Target/LLVMIR/Import/function-attributes.ll (+18)
- (modified) mlir/test/Target/LLVMIR/Import/instructions.ll (+37)
- (modified) mlir/test/Target/LLVMIR/llvmir.mlir (+33)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 31cebdde1aa64..079b4cd87d019 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -51,6 +51,15 @@ def CIR_Dialect : Dialect {
static llvm::StringRef getGlobalCtorsAttrName() { return "cir.global_ctors"; }
static llvm::StringRef getGlobalDtorsAttrName() { return "cir.global_dtors"; }
static llvm::StringRef getOperandSegmentSizesAttrName() { return "operandSegmentSizes"; }
+ static llvm::StringRef getNoCallerSavedRegsAttrName() { return "no_caller_saved_registers"; }
+ static llvm::StringRef getNoCallbackAttrName() { return "nocallback"; }
+ // Note: we have to name this with the underscore instead of the dash like
+ // traditional LLVM-IR does, because the LLVM-IR-Dialect doesn't have a way
+ // of forming names with a dash instead of underscore in its auto-generated
+ // names. TGLexer.cpp(from tablegen) only allows tablegen-names
+ // of a [a-zA-Z0-9_] character regex(numbers only if not first), so there is
+ // no way to get an underscore into this, even with escaping.
+ static llvm::StringRef getModularFormatAttrName() { return "modular_format"; }
void registerAttributes();
void registerTypes();
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 83b1c4e78c4d6..34e0309e3e64e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -129,7 +129,8 @@ void CIRGenModule::constructAttributeList(llvm::StringRef name,
if (info.isNoReturn())
addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
- // TODO(cir): Check/add cmse_nonsecure_call attribute here.
+ // TODO(cir): Implement/check the CSME Nonsecure call attribute here. This
+ // requires being in CSME mode.
addAttributesFromFunctionProtoType(getBuilder(), attrs,
calleeInfo.getCalleeFunctionProtoType());
@@ -159,6 +160,9 @@ void CIRGenModule::constructAttributeList(llvm::StringRef name,
if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
addAttributesFromFunctionProtoType(
getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
+
+ // TODO(cir): When doing 'return attrs' we need to cover the 'NoAlias' for
+ // global allocation functions here.
assert(!cir::MissingFeatures::opCallAttrs());
const CXXMethodDecl *md = dyn_cast<CXXMethodDecl>(func);
@@ -168,8 +172,7 @@ void CIRGenModule::constructAttributeList(llvm::StringRef name,
// virtual function. These attributes are not inherited by overloads.
if (!(attrOnCallSite && isVirtualCall)) {
if (func->isNoReturn())
- attrs.set(cir::CIRDialect::getNoReturnAttrName(),
- mlir::UnitAttr::get(&getMLIRContext()));
+ addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
// TODO(cir): Set NoBuiltinAttr here.
}
}
@@ -186,13 +189,54 @@ void CIRGenModule::constructAttributeList(llvm::StringRef name,
sideEffect = cir::SideEffect::Pure;
}
- assert(!cir::MissingFeatures::opCallAttrs());
- }
+ attrs.set(cir::CIRDialect::getSideEffectAttrName(),
+ cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
+
+ // TODO(cir): When doing 'return attrs' we need to cover the Restrict and
+ // ReturnsNonNull attributes here.
+ if (targetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
+ addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
+ // TODO(cir): Implement 'NoCFCheck' attribute here. This requires
+ // fcf-protection mode.
+ if (targetDecl->hasAttr<LeafAttr>())
+ addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
+ // TODO(cir): Implement 'BPFFastCall' attribute here. This requires C, and
+ // the BPF target.
+
+ // TODO(cir): Detecting 'OptimizeNone' is done here in classic codegen, when
+ // we figure out when to do that, we should do it here.
+ // TODO(cir): AllocSize attr should be done here, but it has some additional
+ // work with forming the correct value for it. Typically this calls into
+ // LLVM to set it correctly, which flattens the elem size and num-elems into
+ // a single value. CIR should probably represent these as two values and
+ // handle the combination during lowering by calling into LLVM.
+
+ // TODO(cir): Quite a few CUDA and OpenCL attributes are added here, like
+ // uniform-work-group-size.
+
+ // TODO(cir): we should also do 'aarch64_pstate_sm_body' here.
+
+ if (auto *modularFormat = targetDecl->getAttr<ModularFormatAttr>()) {
+ FormatAttr *format = targetDecl->getAttr<FormatAttr>();
+ StringRef type = format->getType()->getName();
+ std::string formatIdx = std::to_string(format->getFormatIdx());
+ std::string firstArg = std::to_string(format->getFirstArg());
+ SmallVector<StringRef> args = {
+ type, formatIdx, firstArg,
+ modularFormat->getModularImplFn()->getName(),
+ modularFormat->getImplName()};
+ llvm::append_range(args, modularFormat->aspects());
+ attrs.set(cir::CIRDialect::getModularFormatAttrName(),
+ builder.getStringAttr(llvm::join(args, ",")));
+ }
+ // TODO(cir): We should set nobuiltin and default function attrs here.
+
+ // TODO(cir): There is another region of `if (targetDecl)` that handles
+ // removing some attributes that are necessary modifications of the
+ // default-function attrs. We should do that here.
+ }
assert(!cir::MissingFeatures::opCallAttrs());
-
- attrs.set(cir::CIRDialect::getSideEffectAttrName(),
- cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
}
/// Returns the canonical formal type of the given C++ method.
diff --git a/clang/test/CIR/CodeGen/misc-attrs.cpp b/clang/test/CIR/CodeGen/misc-attrs.cpp
index 837f99275c70d..929316f0f208f 100644
--- a/clang/test/CIR/CodeGen/misc-attrs.cpp
+++ b/clang/test/CIR/CodeGen/misc-attrs.cpp
@@ -32,6 +32,28 @@ extern "C" {
__attribute__((convergent))
void convergent() {}
+ // CIR: cir.func{{.*}}@no_caller_saved_registers() attributes {no_caller_saved_registers} {
+ // LLVM: Function Attrs:
+ // LLVM-NOT: no_caller_saved_registers
+ // LLVM-NEXT: define{{.*}}@no_caller_saved_registers() #[[NCSR_ATTR:.*]] {
+ __attribute__((no_caller_saved_registers))
+ void no_caller_saved_registers() {}
+
+ // CIR: cir.func{{.*}}@leaf() attributes {nocallback} {
+ // LLVM: Function Attrs:
+ // LLVM-NOT: leaf
+ // LLVM-NEXT: define{{.*}}@leaf() #[[LEAF_ATTR:.*]] {
+ __attribute__((leaf))
+ void leaf() {}
+
+ // CIR: cir.func{{.*}}@modular_format({{.*}}) attributes {"modular-format" = "kprintf,1,2,someIdent,someStr,aspect,aspect2"} {
+ // LLVM: Function Attrs:
+ // LLVM-NOT:modular_format
+ // LLVM-NEXT: define{{.*}}@modular_format({{.*}}) #[[MOD_FORMAT_ATTR:.*]] {
+ __attribute__((format(kprintf, 1, 2)))
+ __attribute__((modular_format(someIdent, "someStr", "aspect", "aspect2")))
+ void modular_format(const char *c, ...) {}
+
void caller() {
// CIR: cir.call @returns_twice() {returns_twice} : () -> ()
// LLVM: call void @returns_twice() #[[RT_CALL_ATTR:.*]]
@@ -48,6 +70,18 @@ extern "C" {
// CIR: cir.call @convergent() {convergent} : () -> ()
// LLVM: call void @convergent() #[[CONV_CALL_ATTR:.*]]
convergent();
+
+ // CIR: cir.call @no_caller_saved_registers() {no_caller_saved_registers} : () -> ()
+ // LLVM: call void @no_caller_saved_registers() #[[NCSR_CALL_ATTR:.*]]
+ no_caller_saved_registers();
+
+ // CIR: cir.call @leaf() {nocallback} : () -> ()
+ // LLVM: call void @leaf() #[[LEAF_CALL_ATTR:.*]]
+ leaf();
+
+ // CIR: cir.call @modular_format({{.*}}) {"modular-format" = "kprintf,1,2,someIdent,someStr,aspect,aspect2"} :
+ // LLVM: call void {{.*}}@modular_format({{.*}}) #[[MOD_FORMAT_CALL_ATTR:.*]]
+ modular_format("");
}
}
@@ -56,8 +90,14 @@ extern "C" {
// LLVM: attributes #[[HOT_ATTR]] = {{.*}}hot
// LLVM: attributes #[[ND_ATTR]] = {{.*}}noduplicate
// LLVM: attributes #[[CONV_ATTR]] = {{.*}}convergent
+// LLVM: attributes #[[NCSR_ATTR]] = {{.*}}no_caller_saved_registers
+// LLVM: attributes #[[LEAF_ATTR]] = {{.*}}nocallback
+// LLVM: attributes #[[MOD_FORMAT_ATTR]] = {{.*}}"modular-format"="kprintf,1,2,someIdent,someStr,aspect,aspect2"
// LLVM: attributes #[[RT_CALL_ATTR]] = {{.*}}returns_twice
// LLVM: attributes #[[COLD_CALL_ATTR]] = {{.*}}cold
// LLVM: attributes #[[HOT_CALL_ATTR]] = {{.*}}hot
// LLVM: attributes #[[ND_CALL_ATTR]] = {{.*}}noduplicate
// LLVM: attributes #[[CONV_CALL_ATTR]] = {{.*}}convergent
+// LLVM: attributes #[[NCSR_CALL_ATTR]] = {{.*}}no_caller_saved_registers
+// LLVM: attributes #[[LEAF_CALL_ATTR]] = {{.*}}nocallback
+// LLVM: attributes #[[MOD_FORMAT_CALL_ATTR]] = {{.*}}"modular-format"="kprintf,1,2,someIdent,someStr,aspect,aspect2"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index f6f1c90b481c5..3bf4875678a9d 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -797,6 +797,8 @@ def LLVM_CallOp
UnitAttr:$convergent, UnitAttr:$no_unwind, UnitAttr:$will_return,
UnitAttr:$noreturn, UnitAttr:$returns_twice, UnitAttr:$hot,
UnitAttr:$cold, UnitAttr:$noduplicate,
+ UnitAttr:$no_caller_saved_registers, UnitAttr:$nocallback,
+ OptionalAttr<StrAttr>:$modular_format,
VariadicOfVariadic<LLVM_Type, "op_bundle_sizes">:$op_bundle_operands,
DenseI32ArrayAttr:$op_bundle_sizes,
OptionalAttr<ArrayAttr>:$op_bundle_tags,
@@ -2000,6 +2002,9 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
OptionalAttr<UnitAttr>:$hot,
OptionalAttr<UnitAttr>:$cold,
OptionalAttr<UnitAttr>:$noduplicate,
+ OptionalAttr<UnitAttr>:$no_caller_saved_registers,
+ OptionalAttr<UnitAttr>:$nocallback,
+ OptionalAttr<StrAttr>:$modular_format,
OptionalAttr<LLVM_VecTypeHintAttr>:$vec_type_hint,
OptionalAttr<DenseI32ArrayAttr>:$work_group_size_hint,
OptionalAttr<DenseI32ArrayAttr>:$reqd_work_group_size,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 27d6355c9e221..2ef2a72db81d7 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -997,6 +997,7 @@ void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
/*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
/*noreturn=*/nullptr, /*returns_twice=*/nullptr, /*hot=*/nullptr,
/*cold=*/nullptr, /*noduplicate=*/nullptr,
+ /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr, /*modular_format=*/nullptr,
/*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
/*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
/*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1030,6 +1031,7 @@ void CallOp::build(OpBuilder &builder, OperationState &state,
/*noreturn=*/nullptr,
/*returns_twice=*/nullptr, /*hot=*/nullptr,
/*cold=*/nullptr, /*noduplicate=*/nullptr,
+ /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr, /*modular_format=*/nullptr,
/*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
/*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
/*access_groups=*/nullptr,
@@ -1049,6 +1051,7 @@ void CallOp::build(OpBuilder &builder, OperationState &state,
/*noreturn=*/nullptr,
/*returns_twice=*/nullptr, /*hot=*/nullptr,
/*cold=*/nullptr, /*noduplicate=*/nullptr,
+ /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr, /*modular_format=*/nullptr,
/*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
/*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
/*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1068,6 +1071,7 @@ void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
/*noreturn=*/nullptr,
/*returns_twice=*/nullptr, /*hot=*/nullptr,
/*cold=*/nullptr, /*noduplicate=*/nullptr,
+ /*no_caller_saved_registers=*/nullptr, /*nocallback=*/nullptr, /*modular_format=*/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 31636abfff27f..e818fdaccc2d8 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -437,6 +437,15 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
call->addFnAttr(llvm::Attribute::AlwaysInline);
if (callOp.getInlineHintAttr())
call->addFnAttr(llvm::Attribute::InlineHint);
+ if (callOp.getNoCallerSavedRegistersAttr())
+ call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
+ "no_caller_saved_registers"));
+ if (callOp.getNocallbackAttr())
+ call->addFnAttr(llvm::Attribute::NoCallback);
+ if (StringAttr modFormat = callOp.getModularFormatAttr())
+ call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
+ "modular-format",
+ modFormat.getValue()));
if (failed(moduleTranslation.convertArgAndResultAttrs(callOp, call)))
return failure();
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 928e7a57ae24f..deaeb98d9abdc 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2663,10 +2663,13 @@ static constexpr std::array kExplicitLLVMFuncOpAttributes{
StringLiteral("inlinehint"),
StringLiteral("instrument-function-entry"),
StringLiteral("instrument-function-exit"),
+ StringLiteral("modular-format"),
StringLiteral("memory"),
+ StringLiteral("no_caller_saved_registers"),
StringLiteral("no-infs-fp-math"),
StringLiteral("no-nans-fp-math"),
StringLiteral("no-signed-zeros-fp-math"),
+ StringLiteral("nocallback"),
StringLiteral("noduplicate"),
StringLiteral("noinline"),
StringLiteral("noreturn"),
@@ -2722,6 +2725,13 @@ void ModuleImport::processFunctionAttributes(llvm::Function *func,
funcOp.setHot(true);
if (func->hasFnAttribute(llvm::Attribute::NoDuplicate))
funcOp.setNoduplicate(true);
+ if (func->hasFnAttribute("no_caller_saved_registers"))
+ funcOp.setNoCallerSavedRegisters(true);
+ if (func->hasFnAttribute(llvm::Attribute::NoCallback))
+ funcOp.setNocallback(true);
+ if (llvm::Attribute attr = func->getFnAttribute("modular-format");
+ attr.isStringAttribute())
+ funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
funcOp.setArmStreaming(true);
@@ -2949,6 +2959,13 @@ LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
op.setNoduplicate(
callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
+ op.setNoCallerSavedRegisters(
+ callAttrs.getFnAttr("no_caller_saved_registers").isValid());
+ op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
+
+ if (llvm::Attribute attr = callAttrs.getFnAttr("modular-format");
+ attr.isStringAttribute())
+ op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
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 79d65ffe4e551..7d14efc0b6695 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1686,6 +1686,12 @@ static void convertFunctionAttributes(LLVMFuncOp func,
llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
if (func.getNoreturnAttr())
llvmFunc->addFnAttr(llvm::Attribute::NoReturn);
+ if(func.getNoCallerSavedRegistersAttr())
+ llvmFunc->addFnAttr("no_caller_saved_registers");
+ if (func.getNocallbackAttr())
+ llvmFunc->addFnAttr(llvm::Attribute::NoCallback);
+ if (StringAttr modFormat = func.getModularFormatAttr())
+ llvmFunc->addFnAttr("modular-format", modFormat.getValue());
if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
llvmFunc->addFnAttr("target-features", targetFeatAttr.getFeaturesString());
if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir
index a66087e431eee..7d9cafe05bff0 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -354,6 +354,25 @@ module {
llvm.return
}
+ llvm.func @no_caller_saved_registers_function() attributes {no_caller_saved_registers} {
+ // CHECK: @no_caller_saved_registers_function
+ // CHECK-SAME: attributes {no_caller_saved_registers}
+ llvm.return
+ }
+
+ llvm.func @nocallback_function() attributes {nocallback} {
+ // CHECK: @nocallback_function
+ // CHECK-SAME: attributes {nocallback}
+ llvm.return
+ }
+
+ llvm.func @modular_format_function(%arg: i32) attributes {modular_format = "ident,1,1,foo,bar"} {
+ // CHECK: @modular_format_function
+ // CHECK-SAME: attributes {modular_format = "ident,1,1,foo,bar"}
+ llvm.return
+ }
+
+
}
// -----
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 9ce45afd96c25..c97574f41e8a4 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -137,6 +137,15 @@ func.func @ops(%arg0: i32, %arg1: f32,
// CHECK: llvm.call @baz() {noduplicate} : () -> ()
llvm.call @baz() {noduplicate} : () -> ()
+// CHECK: llvm.call @baz() {no_caller_saved_registers} : () -> ()
+ llvm.call @baz() {no_caller_saved_registers} : () -> ()
+
+// CHECK: llvm.call @baz() {nocallback} : () -> ()
+ llvm.call @baz() {nocallback} : () -> ()
+
+// CHECK: llvm.call @baz() {modular_format = "format str"} : () -> ()
+ llvm.call @baz() {modular_format = "format str"} : () -> ()
+
// 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 1002ad03c227c..153912fbae34a 100644
--- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
@@ -441,5 +441,23 @@ declare void @noduplicate_attribute() noduplicate
// -----
+; CHECK-LABEL: @no_caller_saved_registers_attribute
+; CHECK-SAME: attributes {no_caller_saved_registers}
+declare void @no_caller_saved_registers_attribute () "no_caller_saved_registers"
+
+// -----
+
+; CHECK-LABEL: @nocallback_attribute
+; CHECK-SAME: attributes {nocallback}
+declare void @nocallback_attribute() nocallback
+
+// -----
+
+; CHECK-LABEL: @modular_format_attribute
+; CHECK-SAME: attributes {modular_format = "Ident,1,1,Foo,Bar"}
+declare void @modular_format_attribute(i32) "modular-format" = "Ident,1,1,Foo,Bar"
+
+// -----
+
; 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 11ebd70def8ce..9b3ad17c31a28 100644
--- a/mlir/test/Target/LLVMIR/Import/instructions.ll
+++ b/mlir/test/Target/LLVMIR/Import/instructions.ll
@@ -761,6 +761,43 @@ define void @call_nodupli...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/178443
More information about the cfe-commits
mailing list