Skip to content

Commit 3486f5f

Browse files
committed
[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 Differential Revision: https://reviews.llvm.org/D146633
1 parent b0cd5b2 commit 3486f5f

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

mlir/lib/Dialect/LLVMIR/IR/LLVMInlining.cpp

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
1616
#include "mlir/IR/Matchers.h"
1717
#include "mlir/Transforms/InliningUtils.h"
18+
#include "llvm/Support/Debug.h"
19+
20+
#define DEBUG_TYPE "llvm-inliner"
1821

1922
using namespace mlir;
2023

@@ -134,26 +137,43 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
134137
if (!wouldBeCloned)
135138
return false;
136139
auto callOp = dyn_cast<LLVM::CallOp>(call);
140+
if (!callOp) {
141+
LLVM_DEBUG(llvm::dbgs()
142+
<< "Cannot inline: call is not an LLVM::CallOp\n");
143+
return false;
144+
}
137145
auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(callable);
138-
if (!callOp || !funcOp)
146+
if (!funcOp) {
147+
LLVM_DEBUG(llvm::dbgs()
148+
<< "Cannot inline: callable is not an LLVM::LLVMFuncOp\n");
139149
return false;
150+
}
140151
if (auto attrs = funcOp.getArgAttrs()) {
141152
for (Attribute attr : *attrs) {
142153
auto attrDict = cast<DictionaryAttr>(attr);
143154
for (NamedAttribute attr : attrDict) {
144155
if (attr.getName() == LLVM::LLVMDialect::getByValAttrName())
145156
continue;
146157
// TODO: Handle all argument attributes;
158+
LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName()
159+
<< ": unhandled argument attribute \""
160+
<< attr.getName() << "\"\n");
147161
return false;
148162
}
149163
}
150164
}
151165
// TODO: Handle result attributes;
152-
if (funcOp.getResAttrs())
166+
if (funcOp.getResAttrs()) {
167+
LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName()
168+
<< ": unhandled result attribute\n");
153169
return false;
170+
}
154171
// TODO: Handle exceptions.
155-
if (funcOp.getPersonality())
172+
if (funcOp.getPersonality()) {
173+
LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName()
174+
<< ": unhandled function personality\n");
156175
return false;
176+
}
157177
if (funcOp.getPassthrough()) {
158178
// TODO: Used attributes should not be passthrough.
159179
DenseSet<StringAttr> disallowed(
@@ -167,7 +187,14 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
167187
auto stringAttr = dyn_cast<StringAttr>(attr);
168188
if (!stringAttr)
169189
return false;
170-
return disallowed.contains(stringAttr);
190+
if (disallowed.contains(stringAttr)) {
191+
LLVM_DEBUG(llvm::dbgs()
192+
<< "Cannot inline " << funcOp.getSymName()
193+
<< ": found disallowed function attribute "
194+
<< stringAttr << "\n");
195+
return true;
196+
}
197+
return false;
171198
}))
172199
return false;
173200
}
@@ -185,14 +212,28 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
185212
// Some attributes on memory operations require handling during
186213
// inlining. Since this is not yet implemented, refuse to inline memory
187214
// operations that have any of these attributes.
188-
if (auto iface = dyn_cast<LLVM::AliasAnalysisOpInterface>(op))
189-
if (iface.getAliasScopesOrNull() || iface.getNoAliasScopesOrNull())
215+
if (auto iface = dyn_cast<LLVM::AliasAnalysisOpInterface>(op)) {
216+
if (iface.getAliasScopesOrNull() || iface.getNoAliasScopesOrNull()) {
217+
LLVM_DEBUG(llvm::dbgs()
218+
<< "Cannot inline: unhandled alias analysis metadata\n");
190219
return false;
191-
if (auto iface = dyn_cast<LLVM::AccessGroupOpInterface>(op))
192-
if (iface.getAccessGroupsOrNull())
220+
}
221+
}
222+
if (auto iface = dyn_cast<LLVM::AccessGroupOpInterface>(op)) {
223+
if (iface.getAccessGroupsOrNull()) {
224+
LLVM_DEBUG(llvm::dbgs()
225+
<< "Cannot inline: unhandled access group metadata\n");
193226
return false;
194-
return isa<LLVM::CallOp, LLVM::AllocaOp, LLVM::LifetimeStartOp,
195-
LLVM::LifetimeEndOp, LLVM::LoadOp, LLVM::StoreOp>(op);
227+
}
228+
}
229+
if (!isa<LLVM::CallOp, LLVM::AllocaOp, LLVM::LifetimeStartOp,
230+
LLVM::LifetimeEndOp, LLVM::LoadOp, LLVM::StoreOp>(op)) {
231+
LLVM_DEBUG(llvm::dbgs()
232+
<< "Cannot inline: unhandled side effecting operation \""
233+
<< op->getName() << "\"\n");
234+
return false;
235+
}
236+
return true;
196237
}
197238

198239
/// Handle the given inlined return by replacing it with a branch. This

mlir/test/Dialect/LLVMIR/inlining.mlir

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,29 @@ llvm.func @caller() {
160160

161161
// -----
162162

163-
llvm.func @callee_noinline() attributes { passthrough = ["noinline"] }
164-
llvm.func @callee_optnone() attributes { passthrough = ["optnone"] }
165-
llvm.func @callee_noduplicate() attributes { passthrough = ["noduplicate"] }
166-
llvm.func @callee_presplitcoroutine() attributes { passthrough = ["presplitcoroutine"] }
167-
llvm.func @callee_returns_twice() attributes { passthrough = ["returns_twice"] }
168-
llvm.func @callee_strictfp() attributes { passthrough = ["strictfp"] }
163+
llvm.func @callee_noinline() attributes { passthrough = ["noinline"] } {
164+
llvm.return
165+
}
166+
167+
llvm.func @callee_optnone() attributes { passthrough = ["optnone"] } {
168+
llvm.return
169+
}
170+
171+
llvm.func @callee_noduplicate() attributes { passthrough = ["noduplicate"] } {
172+
llvm.return
173+
}
174+
175+
llvm.func @callee_presplitcoroutine() attributes { passthrough = ["presplitcoroutine"] } {
176+
llvm.return
177+
}
178+
179+
llvm.func @callee_returns_twice() attributes { passthrough = ["returns_twice"] } {
180+
llvm.return
181+
}
182+
183+
llvm.func @callee_strictfp() attributes { passthrough = ["strictfp"] } {
184+
llvm.return
185+
}
169186

170187
// CHECK-LABEL: llvm.func @caller
171188
// CHECK-NEXT: llvm.call @callee_noinline

0 commit comments

Comments
 (0)