diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 423cf948b03e1..9a74a24f80d3b 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -749,6 +749,11 @@ def LLVM_CallOp : LLVM_MemAccessOpBase<"call", the LLVM function type that uses an explicit void type to model functions that do not return a value. + If this operatin has the `no_inline` attribute, then this specific function call + will never be inlined. The opposite behavior will occur if the call has `always_inline` + attribute. The `inline_hint` attribute indicates that it is desirable to inline + this function call. + Examples: ```mlir @@ -778,16 +783,17 @@ def LLVM_CallOp : LLVM_MemAccessOpBase<"call", DefaultValuedAttr:$CConv, DefaultValuedAttr:$TailCallKind, OptionalAttr:$memory_effects, - OptionalAttr:$convergent, - OptionalAttr:$no_unwind, - OptionalAttr:$will_return, + UnitAttr:$convergent, + UnitAttr:$no_unwind, + UnitAttr:$will_return, VariadicOfVariadic:$op_bundle_operands, DenseI32ArrayAttr:$op_bundle_sizes, OptionalAttr:$op_bundle_tags, OptionalAttr:$arg_attrs, OptionalAttr:$res_attrs, - OptionalAttr:$no_inline, - OptionalAttr:$always_inline); + UnitAttr:$no_inline, + UnitAttr:$always_inline, + UnitAttr:$inline_hint); // Append the aliasing related attributes defined in LLVM_MemAccessOpBase. let arguments = !con(args, aliasAttrs); let results = (outs Optional:$result); diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index 252bdd1425d5e..8337a44f7f774 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -1038,7 +1038,8 @@ void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results, /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr, - /*no_inline=*/nullptr, /*always_inline=*/nullptr); + /*no_inline=*/nullptr, /*always_inline=*/nullptr, + /*inline_hint=*/nullptr); } void CallOp::build(OpBuilder &builder, OperationState &state, @@ -1067,7 +1068,8 @@ void CallOp::build(OpBuilder &builder, OperationState &state, /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr, - /*no_inline=*/nullptr, /*always_inline=*/nullptr); + /*no_inline=*/nullptr, /*always_inline=*/nullptr, + /*inline_hint=*/nullptr); } void CallOp::build(OpBuilder &builder, OperationState &state, @@ -1082,7 +1084,8 @@ void CallOp::build(OpBuilder &builder, OperationState &state, /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr, - /*no_inline=*/nullptr, /*always_inline=*/nullptr); + /*no_inline=*/nullptr, /*always_inline=*/nullptr, + /*inline_hint=*/nullptr); } void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func, @@ -1097,7 +1100,8 @@ void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func, /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr, - /*no_inline=*/nullptr, /*always_inline=*/nullptr); + /*no_inline=*/nullptr, /*always_inline=*/nullptr, + /*inline_hint=*/nullptr); } CallInterfaceCallable CallOp::getCallableForCallee() { diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp index 10b68a333bcbd..f737533a1d9b5 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp @@ -323,6 +323,8 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder, call->addFnAttr(llvm::Attribute::NoInline); if (callOp.getAlwaysInlineAttr()) call->addFnAttr(llvm::Attribute::AlwaysInline); + if (callOp.getInlineHintAttr()) + call->addFnAttr(llvm::Attribute::InlineHint); if (failed(convertParameterAndResultAttrs(callOp, call, moduleTranslation))) return failure(); diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index ea141d8b07284..8d48f1549bbaf 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -2334,6 +2334,7 @@ LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst, op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid()); op.setAlwaysInline( callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid()); + op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid()); llvm::MemoryEffects memEffects = inst->getMemoryEffects(); ModRefInfo othermem = convertModRefInfoFromLLVM( diff --git a/mlir/test/Target/LLVMIR/Import/call-attributes.ll b/mlir/test/Target/LLVMIR/Import/call-attributes.ll index 96c61e6e31da8..24f96815ac4c3 100644 --- a/mlir/test/Target/LLVMIR/Import/call-attributes.ll +++ b/mlir/test/Target/LLVMIR/Import/call-attributes.ll @@ -23,3 +23,16 @@ define void @test_call_alwaysinline() { } attributes #0 = { alwaysinline } + +// ----- + +declare void @f() + +; CHECK-LABEL: @test_call_inlinehint +; CHECK: llvm.call @f() {inline_hint} : () -> () +define void @test_call_inlinehint() { + call void @f() #0 + ret void +} + +attributes #0 = { inlinehint } diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index cbd41efdc3015..70c59f9de0cf9 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2649,6 +2649,19 @@ llvm.func @always_inline_call() { // CHECK: #[[ATTRS]] // CHECK-SAME: alwaysinline +// ----- + +llvm.func @f() + +// CHECK-LABEL: @inline_hint_call +// CHECK: call void @f() #[[ATTRS:[0-9]+]] +llvm.func @inline_hint_call() { + llvm.call @f() {inline_hint} : () -> () + llvm.return +} + +// CHECK: #[[ATTRS]] +// CHECK-SAME: inlinehint // -----