Skip to content

Conversation

@junfengd-nv
Copy link
Contributor

This commit fixes the no_inline attribute propagation from func::FuncOp to LLVM::LLVMFuncOp and adds corresponding test coverage. After the change, functions marked with no_inline in the func dialect maintain this optimization hint when lowered to LLVM IR.

@llvmbot llvmbot added the mlir label Jun 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 11, 2025

@llvm/pr-subscribers-mlir

Author: None (junfengd-nv)

Changes

This commit fixes the no_inline attribute propagation from func::FuncOp to LLVM::LLVMFuncOp and adds corresponding test coverage. After the change, functions marked with no_inline in the func dialect maintain this optimization hint when lowered to LLVM IR.


Full diff: https://github.com/llvm/llvm-project/pull/143809.diff

2 Files Affected:

  • (modified) mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp (+6)
  • (modified) mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir (+8)
diff --git a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
index 328c605add65c..35228fb9c9e72 100644
--- a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
+++ b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
@@ -62,6 +62,7 @@ using namespace mlir;
 static constexpr StringRef varargsAttrName = "func.varargs";
 static constexpr StringRef linkageAttrName = "llvm.linkage";
 static constexpr StringRef barePtrAttrName = "llvm.bareptr";
+static constexpr StringRef noInlineAttr = "no_inline";
 
 /// Return `true` if the `op` should use bare pointer calling convention.
 static bool shouldUseBarePtrCallConv(Operation *op,
@@ -381,6 +382,11 @@ mlir::convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp,
     newFuncOp.setMemoryEffectsAttr(memoryAttr);
   }
 
+  // Propagate no_inline attributes
+  if (funcOp->hasAttr(noInlineAttr)) {
+    newFuncOp->setAttr(noInlineAttr, rewriter.getUnitAttr());
+  }
+
   // Propagate argument/result attributes to all converted arguments/result
   // obtained after converting a given original argument/result.
   if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
diff --git a/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir b/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir
index ae1dc70d0686b..b4e6cdffb7640 100644
--- a/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir
+++ b/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir
@@ -96,3 +96,11 @@ func.func private @badllvmlinkage(i32) attributes { "llvm.linkage" = 3 : i64 } /
 func.func @variadic_func(%arg0: i32) attributes { "func.varargs" = true, "llvm.emit_c_interface" } {
   return
 }
+
+// -----
+
+// Check that no_inline attribute is propagated from func::FuncOp to LLVM::LLVMFuncOp
+// CHECK-LABEL: llvm.func @func_with_noinline(%arg0: i32) attributes {no_inline}
+func.func @func_with_noinline(%arg0: i32) attributes { no_inline } {
+  return
+}

@vzakhari
Copy link
Contributor

Thank you, Junfeng! It looks good to me.

Please give Matthias time to also review this.

static constexpr StringRef varargsAttrName = "func.varargs";
static constexpr StringRef linkageAttrName = "llvm.linkage";
static constexpr StringRef barePtrAttrName = "llvm.bareptr";
static constexpr StringRef noInlineAttrName = "no_inline";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not rely on magic constants in local files and get this somehow from the interface or from specific op classes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the comment, @ftynse!

Would that be acceptable to add the get/set interface methods into FunctionOpInterface and then implement it for func.func, llvm.func, etc.? Or did you mean to suggest something else?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't have a specific suggestion, just observed that such action-at-a-distance is dangerous. The op definition may change the name of the attribute to, e.g., noinline without the underscore, and this code will silently break. Adding interface methods would make sense to be, doubly so if these methods are then used in the inliner logic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doubly so if these methods are then used in the inliner logic.

Thanks! It sounds quite reasonable to add such interface methods in FunctionOpInterface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants