Author: Erich Keane Date: 2026-01-30T06:08:41-08:00 New Revision: 6e0881c5414a6c21a1d7e15a04eaae4e240dabc4
URL: https://github.com/llvm/llvm-project/commit/6e0881c5414a6c21a1d7e15a04eaae4e240dabc4 DIFF: https://github.com/llvm/llvm-project/commit/6e0881c5414a6c21a1d7e15a04eaae4e240dabc4.diff LOG: [CIR] 3 more 'quick' function attribute lowering through LLVMIRDialect (#178443) 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. Added: Modified: clang/include/clang/CIR/Dialect/IR/CIRDialect.td clang/lib/CIR/CodeGen/CIRGenCall.cpp clang/test/CIR/CodeGen/misc-attrs.cpp mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp mlir/lib/Target/LLVMIR/ModuleImport.cpp mlir/lib/Target/LLVMIR/ModuleTranslation.cpp mlir/test/Dialect/LLVMIR/func.mlir mlir/test/Dialect/LLVMIR/roundtrip.mlir mlir/test/Target/LLVMIR/Import/function-attributes.ll mlir/test/Target/LLVMIR/Import/instructions.ll mlir/test/Target/LLVMIR/llvmir.mlir Removed: ################################################################################ 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..809d775e77d55 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, ","))); + } - assert(!cir::MissingFeatures::opCallAttrs()); + // TODO(cir): We should set nobuiltin and default function attrs here. - attrs.set(cir::CIRDialect::getSideEffectAttrName(), - cir::SideEffectAttr::get(&getMLIRContext(), sideEffect)); + // 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()); } /// 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..5a6686c5df788 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 41c6b43473aa9..fa7e9e53cfec7 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -997,6 +997,8 @@ 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 +1032,8 @@ 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 +1053,8 @@ 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 +1074,8 @@ 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 eb3a48a213dec..e32719f10d7c1 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 9ddb0c1f13223..437701a48e460 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..e57a54cb43267 100644 --- a/mlir/test/Dialect/LLVMIR/func.mlir +++ b/mlir/test/Dialect/LLVMIR/func.mlir @@ -354,6 +354,24 @@ 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_noduplicate() { ; CHECK: llvm.func @f() declare void @f() +; CHECK-LABEL: @call_no_caller_saved_registers +define void @call_no_caller_saved_registers() { +; CHECK: llvm.call @f() {no_caller_saved_registers} + call void @f() "no_caller_saved_registers" + ret void +} + +; // ----- + +; CHECK: llvm.func @f() +declare void @f() + +; CHECK-LABEL: @call_nocallback +define void @call_nocallback() { +; CHECK: llvm.call @f() {nocallback} + call void @f() nocallback + ret void +} + +; // ----- + +; CHECK: llvm.func @f(i32) +declare void @f(i32) + +; CHECK-LABEL: @call_modular_format +define void @call_modular_format() { +; CHECK: llvm.call @f({{.*}}) {modular_format = "ident,1,1,foo,bar"} + %arg = alloca i32 + call void @f(i32 0) "modular-format" = "ident,1,1,foo,bar" + 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 8adf305805b0e..978199fbfb1a1 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2686,6 +2686,39 @@ llvm.func @noduplicate() attributes { noduplicate } { // ----- +// CHECK-LABEL: @no_caller_saved_registers +// CHECK-SAME: #[[ATTRS:[0-9]+]] +llvm.func @no_caller_saved_registers() attributes { no_caller_saved_registers } { + llvm.return +} + +// CHECK: #[[ATTRS]] +// CHECK-SAME: no_caller_saved_registers + +// ----- + +// CHECK-LABEL: @nocallback +// CHECK-SAME: #[[ATTRS:[0-9]+]] +llvm.func @nocallback() attributes { nocallback } { + llvm.return +} + +// CHECK: #[[ATTRS]] +// CHECK-SAME: nocallback + +// ----- + +// CHECK-LABEL: @modular_format +// CHECK-SAME: #[[ATTRS:[0-9]+]] +llvm.func @modular_format(%arg : i32) attributes { modular_format = "ident,1,1,foo,bar" } { + llvm.return +} + +// CHECK: #[[ATTRS]] +// CHECK-SAME: "modular-format"="ident,1,1,foo,bar" + +// ----- + llvm.func @f() // CHECK-LABEL: @convergent_call _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
