Skip to content

Commit 2bd6642

Browse files
[mlir][dataflow]Fix dense backward dataflow intraprocedural hook (#76865)
The dataflow analysis framework within MLIR allows to customize the transfer function when a `call-like` operation is encuntered. The check to see if the analysis was executed in intraprocedural mode was executed after the check to see if the callee had the CallableOpInterface, and thus intraprocedural analyses would behave as interpocedural ones when performing indirect calls. This commit fixes the issue by performing the check for intraprocedurality first. Dense forward analyses were already behaving correctly. https://github.com/llvm/llvm-project/blob/main/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp#L63 Co-authored-by: massimo <[email protected]>
1 parent 7954c57 commit 2bd6642

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,17 +283,23 @@ void AbstractDenseBackwardDataFlowAnalysis::visitCallOperation(
283283
AbstractDenseLattice *before) {
284284
// Find the callee.
285285
Operation *callee = call.resolveCallable(&symbolTable);
286-
auto callable = dyn_cast_or_null<CallableOpInterface>(callee);
287-
if (!callable)
288-
return setToExitState(before);
289286

287+
auto callable = dyn_cast_or_null<CallableOpInterface>(callee);
290288
// No region means the callee is only declared in this module.
291-
Region *region = callable.getCallableRegion();
292-
if (!region || region->empty() || !getSolverConfig().isInterprocedural()) {
289+
// If that is the case or if the solver is not interprocedural,
290+
// let the hook handle it.
291+
if (!getSolverConfig().isInterprocedural() ||
292+
(callable && (!callable.getCallableRegion() ||
293+
callable.getCallableRegion()->empty()))) {
293294
return visitCallControlFlowTransfer(
294295
call, CallControlFlowAction::ExternalCallee, after, before);
295296
}
296297

298+
if (!callable)
299+
return setToExitState(before);
300+
301+
Region *region = callable.getCallableRegion();
302+
297303
// Call-level control flow specifies the data flow here.
298304
//
299305
// func.func @callee() {

mlir/test/Analysis/DataFlow/test-next-access.mlir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,3 +575,21 @@ func.func @call_opaque_callee(%arg0: memref<f32>) {
575575
memref.load %arg0[] {name = "post"} : memref<f32>
576576
return
577577
}
578+
579+
// -----
580+
581+
// CHECK-LABEL: @indirect_call
582+
func.func @indirect_call(%arg0: memref<f32>, %arg1: (memref<f32>) -> ()) {
583+
// IP: name = "pre"
584+
// IP-SAME: next_access = ["unknown"]
585+
// IP_AR: name = "pre"
586+
// IP_AR-SAME: next_access = ["unknown"]
587+
// LOCAL: name = "pre"
588+
// LOCAL-SAME: next_access = ["unknown"]
589+
// LC_AR: name = "pre"
590+
// LC_AR-SAME: next_access = {{\[}}["call"]]
591+
memref.load %arg0[] {name = "pre"} : memref<f32>
592+
func.call_indirect %arg1(%arg0) {name = "call"} : (memref<f32>) -> ()
593+
memref.load %arg0[] {name = "post"} : memref<f32>
594+
return
595+
}

0 commit comments

Comments
 (0)