diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMInlining.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMInlining.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMInlining.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMInlining.cpp @@ -15,6 +15,9 @@ #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/IR/Matchers.h" #include "mlir/Transforms/InliningUtils.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "llvm-inliner" using namespace mlir; @@ -134,9 +137,17 @@ if (!wouldBeCloned) return false; auto callOp = dyn_cast(call); + if (!callOp) { + LLVM_DEBUG(llvm::dbgs() + << "Cannot inline: call is not an LLVM::CallOp\n"); + return false; + } auto funcOp = dyn_cast(callable); - if (!callOp || !funcOp) + if (!funcOp) { + LLVM_DEBUG(llvm::dbgs() + << "Cannot inline: callable is not an LLVM::LLVMFuncOp\n"); return false; + } if (auto attrs = funcOp.getArgAttrs()) { for (Attribute attr : *attrs) { auto attrDict = cast(attr); @@ -144,16 +155,25 @@ if (attr.getName() == LLVM::LLVMDialect::getByValAttrName()) continue; // TODO: Handle all argument attributes; + LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName() + << ": unhandled argument attribute \"" + << attr.getName() << "\"\n"); return false; } } } // TODO: Handle result attributes; - if (funcOp.getResAttrs()) + if (funcOp.getResAttrs()) { + LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName() + << ": unhandled result attribute\n"); return false; + } // TODO: Handle exceptions. - if (funcOp.getPersonality()) + if (funcOp.getPersonality()) { + LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName() + << ": unhandled function personality\n"); return false; + } if (funcOp.getPassthrough()) { // TODO: Used attributes should not be passthrough. DenseSet disallowed( @@ -167,7 +187,14 @@ auto stringAttr = dyn_cast(attr); if (!stringAttr) return false; - return disallowed.contains(stringAttr); + if (disallowed.contains(stringAttr)) { + LLVM_DEBUG(llvm::dbgs() + << "Cannot inline " << funcOp.getSymName() + << ": found disallowed function attribute " + << stringAttr << "\n"); + return true; + } + return false; })) return false; } @@ -185,14 +212,28 @@ // Some attributes on memory operations require handling during // inlining. Since this is not yet implemented, refuse to inline memory // operations that have any of these attributes. - if (auto iface = dyn_cast(op)) - if (iface.getAliasScopesOrNull() || iface.getNoAliasScopesOrNull()) + if (auto iface = dyn_cast(op)) { + if (iface.getAliasScopesOrNull() || iface.getNoAliasScopesOrNull()) { + LLVM_DEBUG(llvm::dbgs() + << "Cannot inline: unhandled alias analysis metadata\n"); return false; - if (auto iface = dyn_cast(op)) - if (iface.getAccessGroupsOrNull()) + } + } + if (auto iface = dyn_cast(op)) { + if (iface.getAccessGroupsOrNull()) { + LLVM_DEBUG(llvm::dbgs() + << "Cannot inline: unhandled access group metadata\n"); return false; - return isa(op); + } + } + if (!isa(op)) { + LLVM_DEBUG(llvm::dbgs() + << "Cannot inline: unhandled side effecting operation \"" + << op->getName() << "\"\n"); + return false; + } + return true; } /// Handle the given inlined return by replacing it with a branch. This diff --git a/mlir/test/Dialect/LLVMIR/inlining.mlir b/mlir/test/Dialect/LLVMIR/inlining.mlir --- a/mlir/test/Dialect/LLVMIR/inlining.mlir +++ b/mlir/test/Dialect/LLVMIR/inlining.mlir @@ -160,12 +160,29 @@ // ----- -llvm.func @callee_noinline() attributes { passthrough = ["noinline"] } -llvm.func @callee_optnone() attributes { passthrough = ["optnone"] } -llvm.func @callee_noduplicate() attributes { passthrough = ["noduplicate"] } -llvm.func @callee_presplitcoroutine() attributes { passthrough = ["presplitcoroutine"] } -llvm.func @callee_returns_twice() attributes { passthrough = ["returns_twice"] } -llvm.func @callee_strictfp() attributes { passthrough = ["strictfp"] } +llvm.func @callee_noinline() attributes { passthrough = ["noinline"] } { + llvm.return +} + +llvm.func @callee_optnone() attributes { passthrough = ["optnone"] } { + llvm.return +} + +llvm.func @callee_noduplicate() attributes { passthrough = ["noduplicate"] } { + llvm.return +} + +llvm.func @callee_presplitcoroutine() attributes { passthrough = ["presplitcoroutine"] } { + llvm.return +} + +llvm.func @callee_returns_twice() attributes { passthrough = ["returns_twice"] } { + llvm.return +} + +llvm.func @callee_strictfp() attributes { passthrough = ["strictfp"] } { + llvm.return +} // CHECK-LABEL: llvm.func @caller // CHECK-NEXT: llvm.call @callee_noinline