[MLIR][LLVM] Add debug output to the LLVM inliner.

This revealed a test case that wasn't hitting the intended branch
because the inlinees had no function definition.

Depends on D146628

Reviewed By: gysit

Differential Revision: https://reviews.llvm.org/D146633
This commit is contained in:
Johannes de Fine Licht
2023-03-24 09:27:27 +01:00
committed by Tobias Gysi
parent 09aa3f7bb5
commit a94d2bd5b5
2 changed files with 75 additions and 17 deletions

View File

@@ -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 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
if (!wouldBeCloned)
return false;
auto callOp = dyn_cast<LLVM::CallOp>(call);
auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(callable);
if (!callOp || !funcOp)
if (!callOp) {
LLVM_DEBUG(llvm::dbgs()
<< "Cannot inline: call is not an LLVM::CallOp\n");
return false;
}
auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(callable);
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<DictionaryAttr>(attr);
@@ -144,16 +155,25 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
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<StringAttr> disallowed(
@@ -167,7 +187,14 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
auto stringAttr = dyn_cast<StringAttr>(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 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
// 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<LLVM::AliasAnalysisOpInterface>(op))
if (iface.getAliasScopesOrNull() || iface.getNoAliasScopesOrNull())
if (auto iface = dyn_cast<LLVM::AliasAnalysisOpInterface>(op)) {
if (iface.getAliasScopesOrNull() || iface.getNoAliasScopesOrNull()) {
LLVM_DEBUG(llvm::dbgs()
<< "Cannot inline: unhandled alias analysis metadata\n");
return false;
if (auto iface = dyn_cast<LLVM::AccessGroupOpInterface>(op))
if (iface.getAccessGroupsOrNull())
}
}
if (auto iface = dyn_cast<LLVM::AccessGroupOpInterface>(op)) {
if (iface.getAccessGroupsOrNull()) {
LLVM_DEBUG(llvm::dbgs()
<< "Cannot inline: unhandled access group metadata\n");
return false;
return isa<LLVM::CallOp, LLVM::AllocaOp, LLVM::LifetimeStartOp,
LLVM::LifetimeEndOp, LLVM::LoadOp, LLVM::StoreOp>(op);
}
}
if (!isa<LLVM::CallOp, LLVM::AllocaOp, LLVM::LifetimeStartOp,
LLVM::LifetimeEndOp, LLVM::LoadOp, LLVM::StoreOp>(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

View File

@@ -160,12 +160,29 @@ llvm.func @caller() {
// -----
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