[Mlir-commits] [mlir] [MLIR] Fixup the LDBG() logging in dataflow/deadcodeanalysis (NFC) (PR #155085)
Mehdi Amini
llvmlistbot at llvm.org
Sat Aug 23 02:50:45 PDT 2025
https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/155085
>From 7112f13c7656042441ddc5e2f80dbb4fd05576a1 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 23 Aug 2025 02:45:17 -0700
Subject: [PATCH] [MLIR] Fixup the LDBG() logging in dataflow/deadcodeanalysis
(NFC)
This is improving the debug output:
- avoid printing pointers, print ops without regions in general.
- skip extra new-lines in the output
- minor other consistency aspects.
---
mlir/include/mlir/IR/Operation.h | 8 +-
.../Analysis/DataFlow/DeadCodeAnalysis.cpp | 85 +++--
mlir/lib/Analysis/DataFlowFramework.cpp | 9 +-
mlir/test/Transforms/sccp-callgraph.mlir | 290 +-----------------
4 files changed, 68 insertions(+), 324 deletions(-)
diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h
index 4f89f8b85861e..5569392cf0b41 100644
--- a/mlir/include/mlir/IR/Operation.h
+++ b/mlir/include/mlir/IR/Operation.h
@@ -1106,6 +1106,8 @@ inline raw_ostream &operator<<(raw_ostream &os, const Operation &op) {
/// useful to act as a "stream modifier" to customize printing an operation
/// with a stream using the operator<< overload, e.g.:
/// llvm::dbgs() << OpWithFlags(op, OpPrintingFlags().skipRegions());
+/// This always prints the operation with the local scope, to avoid introducing
+/// spurious newlines in the stream.
class OpWithFlags {
public:
OpWithFlags(Operation *op, OpPrintingFlags flags = {})
@@ -1116,11 +1118,11 @@ class OpWithFlags {
private:
Operation *op;
OpPrintingFlags theFlags;
- friend raw_ostream &operator<<(raw_ostream &os, const OpWithFlags &op);
+ friend raw_ostream &operator<<(raw_ostream &os, OpWithFlags op);
};
-inline raw_ostream &operator<<(raw_ostream &os,
- const OpWithFlags &opWithFlags) {
+inline raw_ostream &operator<<(raw_ostream &os, OpWithFlags opWithFlags) {
+ opWithFlags.flags().useLocalScope();
opWithFlags.op->print(os, opWithFlags.flags());
return os;
}
diff --git a/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp b/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
index 4addff9610e88..9424eff3e6b6f 100644
--- a/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
@@ -79,9 +79,17 @@ void Executable::onUpdate(DataFlowSolver *solver) const {
void PredecessorState::print(raw_ostream &os) const {
if (allPredecessorsKnown())
os << "(all) ";
- os << "predecessors:\n";
- for (Operation *op : getKnownPredecessors())
- os << " " << *op << "\n";
+ os << "predecessors:";
+ if (getKnownPredecessors().empty())
+ os << " (none)";
+ else
+ os << "\n";
+ llvm::interleave(
+ getKnownPredecessors(), os,
+ [&](Operation *op) {
+ os << " " << OpWithFlags(op, OpPrintingFlags().skipRegions());
+ },
+ "\n");
}
ChangeResult PredecessorState::join(Operation *predecessor) {
@@ -128,7 +136,7 @@ DeadCodeAnalysis::DeadCodeAnalysis(DataFlowSolver &solver)
LogicalResult DeadCodeAnalysis::initialize(Operation *top) {
LDBG() << "Initializing DeadCodeAnalysis for top-level op: "
- << top->getName();
+ << OpWithFlags(top, OpPrintingFlags().skipRegions());
// Mark the top-level blocks as executable.
for (Region ®ion : top->getRegions()) {
if (region.empty())
@@ -136,7 +144,8 @@ LogicalResult DeadCodeAnalysis::initialize(Operation *top) {
auto *state =
getOrCreate<Executable>(getProgramPointBefore(®ion.front()));
propagateIfChanged(state, state->setToLive());
- LDBG() << "Marked entry block live for region in op: " << top->getName();
+ LDBG() << "Marked entry block live for region in op: "
+ << OpWithFlags(top, OpPrintingFlags().skipRegions());
}
// Mark as overdefined the predecessors of symbol callables with potentially
@@ -151,14 +160,16 @@ void DeadCodeAnalysis::initializeSymbolCallables(Operation *top) {
<< OpWithFlags(top, OpPrintingFlags().skipRegions());
analysisScope = top;
auto walkFn = [&](Operation *symTable, bool allUsesVisible) {
- LDBG() << "[init] Processing symbol table op: " << symTable->getName();
+ LDBG() << "[init] Processing symbol table op: "
+ << OpWithFlags(symTable, OpPrintingFlags().skipRegions());
Region &symbolTableRegion = symTable->getRegion(0);
Block *symbolTableBlock = &symbolTableRegion.front();
bool foundSymbolCallable = false;
for (auto callable : symbolTableBlock->getOps<CallableOpInterface>()) {
LDBG() << "[init] Found CallableOpInterface: "
- << callable.getOperation()->getName();
+ << OpWithFlags(callable.getOperation(),
+ OpPrintingFlags().skipRegions());
Region *callableRegion = callable.getCallableRegion();
if (!callableRegion)
continue;
@@ -173,7 +184,8 @@ void DeadCodeAnalysis::initializeSymbolCallables(Operation *top) {
getOrCreate<PredecessorState>(getProgramPointAfter(callable));
propagateIfChanged(state, state->setHasUnknownPredecessors());
LDBG() << "[init] Marked callable as having unknown predecessors: "
- << callable.getOperation()->getName();
+ << OpWithFlags(callable.getOperation(),
+ OpPrintingFlags().skipRegions());
}
foundSymbolCallable = true;
}
@@ -196,7 +208,8 @@ void DeadCodeAnalysis::initializeSymbolCallables(Operation *top) {
propagateIfChanged(state, state->setHasUnknownPredecessors());
LDBG() << "[init] Marked nested callable as "
"having unknown predecessors: "
- << callable.getOperation()->getName();
+ << OpWithFlags(callable.getOperation(),
+ OpPrintingFlags().skipRegions());
});
}
@@ -212,7 +225,7 @@ void DeadCodeAnalysis::initializeSymbolCallables(Operation *top) {
propagateIfChanged(state, state->setHasUnknownPredecessors());
LDBG() << "[init] Found non-call use for symbol, "
"marked as having unknown predecessors: "
- << symbol->getName();
+ << OpWithFlags(symbol, OpPrintingFlags().skipRegions());
}
};
SymbolTable::walkSymbolTables(top, /*allSymUsesVisible=*/!top->getBlock(),
@@ -235,7 +248,8 @@ LogicalResult DeadCodeAnalysis::initializeRecursively(Operation *op) {
// Initialize the analysis by visiting every op with control-flow semantics.
if (op->getNumRegions() || op->getNumSuccessors() ||
isRegionOrCallableReturn(op) || isa<CallOpInterface>(op)) {
- LDBG() << "[init] Visiting op with control-flow semantics: " << *op;
+ LDBG() << "[init] Visiting op with control-flow semantics: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
// When the liveness of the parent block changes, make sure to
// re-invoke the analysis on the op.
if (op->getBlock())
@@ -247,7 +261,8 @@ LogicalResult DeadCodeAnalysis::initializeRecursively(Operation *op) {
}
// Recurse on nested operations.
for (Region ®ion : op->getRegions()) {
- LDBG() << "[init] Recursing into region of op: " << op->getName();
+ LDBG() << "[init] Recursing into region of op: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
for (Operation &nestedOp : region.getOps()) {
LDBG() << "[init] Recursing into nested op: "
<< OpWithFlags(&nestedOp, OpPrintingFlags().skipRegions());
@@ -270,14 +285,16 @@ void DeadCodeAnalysis::markEdgeLive(Block *from, Block *to) {
}
void DeadCodeAnalysis::markEntryBlocksLive(Operation *op) {
- LDBG() << "Marking entry blocks live for op: " << op->getName();
+ LDBG() << "Marking entry blocks live for op: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
for (Region ®ion : op->getRegions()) {
if (region.empty())
continue;
auto *state =
getOrCreate<Executable>(getProgramPointBefore(®ion.front()));
propagateIfChanged(state, state->setToLive());
- LDBG() << "Marked entry block live for region in op: " << op->getName();
+ LDBG() << "Marked entry block live for region in op: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
}
}
@@ -286,19 +303,22 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
if (point->isBlockStart())
return success();
Operation *op = point->getPrevOp();
- LDBG() << "Visiting operation: " << *op;
+ LDBG() << "Visiting operation: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
// If the parent block is not executable, there is nothing to do.
if (op->getBlock() != nullptr &&
!getOrCreate<Executable>(getProgramPointBefore(op->getBlock()))
->isLive()) {
- LDBG() << "Parent block not live, skipping op: " << *op;
+ LDBG() << "Parent block not live, skipping op: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
return success();
}
// We have a live call op. Add this as a live predecessor of the callee.
if (auto call = dyn_cast<CallOpInterface>(op)) {
- LDBG() << "Visiting call operation: " << *op;
+ LDBG() << "Visiting call operation: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
visitCallOperation(call);
}
@@ -306,12 +326,14 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
if (op->getNumRegions()) {
// Check if we can reason about the region control-flow.
if (auto branch = dyn_cast<RegionBranchOpInterface>(op)) {
- LDBG() << "Visiting region branch operation: " << *op;
+ LDBG() << "Visiting region branch operation: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
visitRegionBranchOperation(branch);
// Check if this is a callable operation.
} else if (auto callable = dyn_cast<CallableOpInterface>(op)) {
- LDBG() << "Visiting callable operation: " << *op;
+ LDBG() << "Visiting callable operation: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
const auto *callsites = getOrCreateFor<PredecessorState>(
getProgramPointAfter(op), getProgramPointAfter(callable));
@@ -323,19 +345,22 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
// Otherwise, conservatively mark all entry blocks as executable.
} else {
- LDBG() << "Marking all entry blocks live for op: " << *op;
+ LDBG() << "Marking all entry blocks live for op: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
markEntryBlocksLive(op);
}
}
if (isRegionOrCallableReturn(op)) {
if (auto branch = dyn_cast<RegionBranchOpInterface>(op->getParentOp())) {
- LDBG() << "Visiting region terminator: " << *op;
+ LDBG() << "Visiting region terminator: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
// Visit the exiting terminator of a region.
visitRegionTerminator(op, branch);
} else if (auto callable =
dyn_cast<CallableOpInterface>(op->getParentOp())) {
- LDBG() << "Visiting callable terminator: " << *op;
+ LDBG() << "Visiting callable terminator: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
// Visit the exiting terminator of a callable.
visitCallableTerminator(op, callable);
}
@@ -344,12 +369,14 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
if (op->getNumSuccessors()) {
// Check if we can reason about the control-flow.
if (auto branch = dyn_cast<BranchOpInterface>(op)) {
- LDBG() << "Visiting branch operation: " << *op;
+ LDBG() << "Visiting branch operation: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
visitBranchOperation(branch);
// Otherwise, conservatively mark all successors as exectuable.
} else {
- LDBG() << "Marking all successors live for op: " << *op;
+ LDBG() << "Marking all successors live for op: "
+ << OpWithFlags(op, OpPrintingFlags().skipRegions());
for (Block *successor : op->getSuccessors())
markEdgeLive(op->getBlock(), successor);
}
@@ -359,7 +386,8 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
}
void DeadCodeAnalysis::visitCallOperation(CallOpInterface call) {
- LDBG() << "visitCallOperation: " << call.getOperation()->getName();
+ LDBG() << "visitCallOperation: "
+ << OpWithFlags(call.getOperation(), OpPrintingFlags().skipRegions());
Operation *callableOp = call.resolveCallableInTable(&symbolTable);
// A call to a externally-defined callable has unknown predecessors.
@@ -442,7 +470,8 @@ void DeadCodeAnalysis::visitBranchOperation(BranchOpInterface branch) {
void DeadCodeAnalysis::visitRegionBranchOperation(
RegionBranchOpInterface branch) {
- LDBG() << "visitRegionBranchOperation: " << branch.getOperation()->getName();
+ LDBG() << "visitRegionBranchOperation: "
+ << OpWithFlags(branch.getOperation(), OpPrintingFlags().skipRegions());
// Try to deduce which regions are executable.
std::optional<SmallVector<Attribute>> operands = getOperandValues(branch);
if (!operands)
@@ -519,14 +548,14 @@ void DeadCodeAnalysis::visitCallableTerminator(Operation *op,
if (canResolve) {
propagateIfChanged(predecessors, predecessors->join(op));
LDBG() << "Added callable terminator as predecessor for callsite: "
- << predecessor->getName();
+ << OpWithFlags(predecessor, OpPrintingFlags().skipRegions());
} else {
// If the terminator is not a return-like, then conservatively assume we
// can't resolve the predecessor.
propagateIfChanged(predecessors,
predecessors->setHasUnknownPredecessors());
LDBG() << "Could not resolve callable terminator for callsite: "
- << predecessor->getName();
+ << OpWithFlags(predecessor, OpPrintingFlags().skipRegions());
}
}
}
diff --git a/mlir/lib/Analysis/DataFlowFramework.cpp b/mlir/lib/Analysis/DataFlowFramework.cpp
index 76bf94aed9e02..7e1b4052027d3 100644
--- a/mlir/lib/Analysis/DataFlowFramework.cpp
+++ b/mlir/lib/Analysis/DataFlowFramework.cpp
@@ -62,11 +62,12 @@ void ProgramPoint::print(raw_ostream &os) const {
return;
}
if (!isBlockStart()) {
- os << "<after operation>:";
- return getPrevOp()->print(os, OpPrintingFlags().skipRegions());
+ os << "<after operation>:"
+ << OpWithFlags(getPrevOp(), OpPrintingFlags().skipRegions());
+ return;
}
- os << "<before operation>:";
- return getNextOp()->print(os, OpPrintingFlags().skipRegions());
+ os << "<before operation>:"
+ << OpWithFlags(getNextOp(), OpPrintingFlags().skipRegions());
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Transforms/sccp-callgraph.mlir b/mlir/test/Transforms/sccp-callgraph.mlir
index f31f749b6e75a..f575a3f6d614e 100644
--- a/mlir/test/Transforms/sccp-callgraph.mlir
+++ b/mlir/test/Transforms/sccp-callgraph.mlir
@@ -2,278 +2,6 @@
// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(builtin.module(sccp))" -split-input-file | FileCheck %s --check-prefix=NESTED
// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(sccp))" -split-input-file | FileCheck %s --check-prefix=FUNC
-/// Check that a constant is properly propagated through the arguments and
-/// results of a private function.
-
-// CHECK-LABEL: func private @private(
-func.func private @private(%arg0 : i32) -> i32 {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: return %[[CST]] : i32
-
- return %arg0 : i32
-}
-
-// CHECK-LABEL: func @simple_private(
-func.func @simple_private() -> i32 {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: return %[[CST]] : i32
-
- %1 = arith.constant 1 : i32
- %result = call @private(%1) : (i32) -> i32
- return %result : i32
-}
-
-// -----
-
-/// Check that a constant is properly propagated through the arguments and
-/// results of a visible nested function.
-
-// CHECK: func nested @nested(
-func.func nested @nested(%arg0 : i32) -> i32 {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: return %[[CST]] : i32
-
- return %arg0 : i32
-}
-
-// CHECK-LABEL: func @simple_nested(
-func.func @simple_nested() -> i32 {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: return %[[CST]] : i32
-
- %1 = arith.constant 1 : i32
- %result = call @nested(%1) : (i32) -> i32
- return %result : i32
-}
-
-// -----
-
-/// Check that non-visible nested functions do not track arguments.
-module {
- // NESTED-LABEL: module @nested_module
- module @nested_module attributes { sym_visibility = "public" } {
-
- // NESTED: func nested @nested(
- func.func nested @nested(%arg0 : i32) -> (i32, i32) {
- // NESTED: %[[CST:.*]] = arith.constant 1 : i32
- // NESTED: return %[[CST]], %arg0 : i32, i32
-
- %1 = arith.constant 1 : i32
- return %1, %arg0 : i32, i32
- }
-
- // NESTED: func @nested_not_all_uses_visible(
- func.func @nested_not_all_uses_visible() -> (i32, i32) {
- // NESTED: %[[CST:.*]] = arith.constant 1 : i32
- // NESTED: %[[CALL:.*]]:2 = call @nested
- // NESTED: return %[[CST]], %[[CALL]]#1 : i32, i32
-
- %1 = arith.constant 1 : i32
- %result:2 = call @nested(%1) : (i32) -> (i32, i32)
- return %result#0, %result#1 : i32, i32
- }
- }
-}
-
-// -----
-
-/// Check that public functions do not track arguments.
-
-// CHECK-LABEL: func @public(
-func.func @public(%arg0 : i32) -> (i32, i32) {
- %1 = arith.constant 1 : i32
- return %1, %arg0 : i32, i32
-}
-
-// CHECK-LABEL: func @simple_public(
-func.func @simple_public() -> (i32, i32) {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: %[[CALL:.*]]:2 = call @public
- // CHECK: return %[[CST]], %[[CALL]]#1 : i32, i32
-
- %1 = arith.constant 1 : i32
- %result:2 = call @public(%1) : (i32) -> (i32, i32)
- return %result#0, %result#1 : i32, i32
-}
-
-// -----
-
-/// Check that functions with non-call users don't have arguments tracked.
-
-func.func private @callable(%arg0 : i32) -> (i32, i32) {
- %1 = arith.constant 1 : i32
- return %1, %arg0 : i32, i32
-}
-
-// CHECK-LABEL: func @non_call_users(
-func.func @non_call_users() -> (i32, i32) {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: %[[CALL:.*]]:2 = call @callable
- // CHECK: return %[[CST]], %[[CALL]]#1 : i32, i32
-
- %1 = arith.constant 1 : i32
- %result:2 = call @callable(%1) : (i32) -> (i32, i32)
- return %result#0, %result#1 : i32, i32
-}
-
-"live.user"() {uses = [@callable]} : () -> ()
-
-// -----
-
-/// Check that return values are overdefined in the presence of an unknown terminator.
-
-func.func private @callable(%arg0 : i32) -> i32 {
- "unknown.return"(%arg0) : (i32) -> ()
-}
-
-// CHECK-LABEL: func @unknown_terminator(
-func.func @unknown_terminator() -> i32 {
- // CHECK: %[[CALL:.*]] = call @callable
- // CHECK: return %[[CALL]] : i32
-
- %1 = arith.constant 1 : i32
- %result = call @callable(%1) : (i32) -> i32
- return %result : i32
-}
-
-// -----
-
-/// Check that return values are overdefined when the constant conflicts.
-
-func.func private @callable(%arg0 : i32) -> i32 {
- return %arg0 : i32
-}
-
-// CHECK-LABEL: func @conflicting_constant(
-func.func @conflicting_constant() -> (i32, i32) {
- // CHECK: %[[CALL1:.*]] = call @callable
- // CHECK: %[[CALL2:.*]] = call @callable
- // CHECK: return %[[CALL1]], %[[CALL2]] : i32, i32
-
- %1 = arith.constant 1 : i32
- %2 = arith.constant 2 : i32
- %result = call @callable(%1) : (i32) -> i32
- %result2 = call @callable(%2) : (i32) -> i32
- return %result, %result2 : i32, i32
-}
-
-// -----
-
-/// Check that return values are overdefined when the constant conflicts with a
-/// non-constant.
-
-func.func private @callable(%arg0 : i32) -> i32 {
- "unknown.return"(%arg0) : (i32) -> ()
-}
-
-// CHECK-LABEL: func @conflicting_constant(
-func.func @conflicting_constant(%arg0 : i32) -> (i32, i32) {
- // CHECK: %[[CALL1:.*]] = call @callable
- // CHECK: %[[CALL2:.*]] = call @callable
- // CHECK: return %[[CALL1]], %[[CALL2]] : i32, i32
-
- %1 = arith.constant 1 : i32
- %result = call @callable(%1) : (i32) -> i32
- %result2 = call @callable(%arg0) : (i32) -> i32
- return %result, %result2 : i32, i32
-}
-
-// -----
-
-/// Check a more complex interaction with calls and control flow.
-
-// CHECK-LABEL: func private @complex_inner_if(
-func.func private @complex_inner_if(%arg0 : i32) -> i32 {
- // CHECK-DAG: %[[TRUE:.*]] = arith.constant true
- // CHECK-DAG: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: cf.cond_br %[[TRUE]], ^bb1
-
- %cst_20 = arith.constant 20 : i32
- %cond = arith.cmpi ult, %arg0, %cst_20 : i32
- cf.cond_br %cond, ^bb1, ^bb2
-
-^bb1:
- // CHECK: ^bb1:
- // CHECK: return %[[CST]] : i32
-
- %cst_1 = arith.constant 1 : i32
- return %cst_1 : i32
-
-^bb2:
- %cst_1_2 = arith.constant 1 : i32
- %arg_inc = arith.addi %arg0, %cst_1_2 : i32
- return %arg_inc : i32
-}
-
-func.func private @complex_cond() -> i1
-
-// CHECK-LABEL: func private @complex_callee(
-func.func private @complex_callee(%arg0 : i32) -> i32 {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
-
- %loop_cond = call @complex_cond() : () -> i1
- cf.cond_br %loop_cond, ^bb1, ^bb2
-
-^bb1:
- // CHECK: ^bb1:
- // CHECK-NEXT: return %[[CST]] : i32
- return %arg0 : i32
-
-^bb2:
- // CHECK: ^bb2:
- // CHECK: call @complex_inner_if(%[[CST]]) : (i32) -> i32
- // CHECK: call @complex_callee(%[[CST]]) : (i32) -> i32
- // CHECK: return %[[CST]] : i32
-
- %updated_arg = call @complex_inner_if(%arg0) : (i32) -> i32
- %res = call @complex_callee(%updated_arg) : (i32) -> i32
- return %res : i32
-}
-
-// CHECK-LABEL: func @complex_caller(
-func.func @complex_caller(%arg0 : i32) -> i32 {
- // CHECK: %[[CST:.*]] = arith.constant 1 : i32
- // CHECK: return %[[CST]] : i32
-
- %1 = arith.constant 1 : i32
- %result = call @complex_callee(%1) : (i32) -> i32
- return %result : i32
-}
-
-// -----
-
-/// Check that non-symbol defining callables currently go to overdefined.
-
-// CHECK-LABEL: func @non_symbol_defining_callable
-func.func @non_symbol_defining_callable() -> i32 {
- // CHECK: %[[RES:.*]] = call_indirect
- // CHECK: return %[[RES]] : i32
-
- %fn = "test.functional_region_op"() ({
- %1 = arith.constant 1 : i32
- "test.return"(%1) : (i32) -> ()
- }) : () -> (() -> i32)
- %res = call_indirect %fn() : () -> (i32)
- return %res : i32
-}
-
-// -----
-
-/// Check that private callables don't get processed if they have no uses.
-
-// CHECK-LABEL: func private @unreferenced_private_function
-func.func private @unreferenced_private_function() -> i32 {
- // CHECK: %[[RES:.*]] = arith.select
- // CHECK: return %[[RES]] : i32
- %true = arith.constant true
- %cst0 = arith.constant 0 : i32
- %cst1 = arith.constant 1 : i32
- %result = arith.select %true, %cst0, %cst1 : i32
- return %result : i32
-}
-
-// -----
-
/// Check that callables outside the analysis scope are marked as external.
func.func private @foo() -> index {
@@ -287,22 +15,6 @@ func.func @bar(%arg0: index) -> index {
// CHECK: %[[C10:.*]] = arith.constant 10
%c0 = arith.constant 0 : index
%1 = arith.constant 420 : index
- %7 = arith.cmpi eq, %arg0, %c0 : index
- cf.cond_br %7, ^bb1(%1 : index), ^bb2
-
-// CHECK: ^bb1(%[[ARG:.*]]: index):
-// FUNC: ^bb1(%[[ARG:.*]]: index):
-^bb1(%8: index): // 2 preds: ^bb0, ^bb4
- // CHECK-NEXT: return %[[ARG]]
- // FUNC-NEXT: return %[[ARG]]
- return %8 : index
-
-// CHECK: ^bb2
-// FUNC: ^bb2
-^bb2:
- // FUNC-NEXT: %[[FOO:.*]] = call @foo
%13 = call @foo() : () -> index
- // CHECK: cf.br ^bb1(%[[C10]]
- // FUNC: cf.br ^bb1(%[[FOO]]
- cf.br ^bb1(%13 : index)
+ return %13 : index
}
More information about the Mlir-commits
mailing list