[Mlir-commits] [mlir] [mlir-c] Add slice analysis and topological sort (PR #206550)
Maksim Levental
llvmlistbot at llvm.org
Mon Jun 29 11:51:10 PDT 2026
https://github.com/makslevental updated https://github.com/llvm/llvm-project/pull/206550
>From a0f26dbcc6fe055228e43e8afe30f3d54a171469 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Mon, 29 Jun 2026 10:58:28 -0700
Subject: [PATCH 1/3] [mlir-c] Add forward slice analysis
---
mlir/include/mlir-c/Analysis.h | 44 ++++++++++++++++++++
mlir/lib/CAPI/IR/Analysis.cpp | 40 ++++++++++++++++++
mlir/lib/CAPI/IR/CMakeLists.txt | 2 +
mlir/test/CAPI/ir.c | 74 +++++++++++++++++++++++++++++++++
4 files changed, 160 insertions(+)
create mode 100644 mlir/include/mlir-c/Analysis.h
create mode 100644 mlir/lib/CAPI/IR/Analysis.cpp
diff --git a/mlir/include/mlir-c/Analysis.h b/mlir/include/mlir-c/Analysis.h
new file mode 100644
index 0000000000000..8e0da6344b5f8
--- /dev/null
+++ b/mlir/include/mlir-c/Analysis.h
@@ -0,0 +1,44 @@
+//===- Analysis.h - C API for MLIR Analysis Utilities -------------*- C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_C_ANALYSIS_H
+#define MLIR_C_ANALYSIS_H
+
+#include "mlir-c/IR.h"
+#include "mlir-c/Support.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//===----------------------------------------------------------------------===//
+// Slice analysis
+//===----------------------------------------------------------------------===//
+
+/// Filter callback for slice analysis, corresponding to
+/// `mlir::SliceOptions::filter`. Return true to keep traversing through the
+/// given operation, false to treat it as a frontier and stop propagation.
+typedef bool (*MlirSliceFilterCallback)(MlirOperation op, void *userData);
+
+/// Computes the forward slice of the given operation, i.e. all its transitive
+/// users, not including the operation itself. The result operations are written
+/// (in slice order) into the caller-allocated `slice` buffer, up to `n`
+/// entries; the total number of operations in the slice is returned (which may
+/// exceed `n`). Passing `n == 0` (with `slice` ignored) queries the size.
+/// `filter` may be NULL to traverse all operations; otherwise it acts as a
+/// frontier (see MlirSliceFilterCallback).
+MLIR_CAPI_EXPORTED intptr_t mlirGetForwardSlice(MlirOperation op,
+ MlirSliceFilterCallback filter,
+ void *filterUserData,
+ intptr_t n, MlirOperation *slice);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MLIR_C_ANALYSIS_H
diff --git a/mlir/lib/CAPI/IR/Analysis.cpp b/mlir/lib/CAPI/IR/Analysis.cpp
new file mode 100644
index 0000000000000..dae2d4e514f3f
--- /dev/null
+++ b/mlir/lib/CAPI/IR/Analysis.cpp
@@ -0,0 +1,40 @@
+//===- Analysis.cpp - C API for MLIR Analysis Utilities -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir-c/Analysis.h"
+
+#include "mlir/Analysis/SliceAnalysis.h"
+#include "mlir/CAPI/IR.h"
+#include "mlir/CAPI/Support.h"
+
+#include <algorithm>
+
+using namespace mlir;
+
+/// Copies up to `n` operations from `slice` into the caller-provided `result`
+/// buffer (wrapping each), returning the total number of operations.
+static intptr_t copySlice(const SetVector<Operation *> &slice, intptr_t n,
+ MlirOperation *result) {
+ intptr_t count = static_cast<intptr_t>(slice.size());
+ for (intptr_t i = 0, e = std::min(count, n); i < e; ++i)
+ result[i] = wrap(slice[i]);
+ return count;
+}
+
+intptr_t mlirGetForwardSlice(MlirOperation op, MlirSliceFilterCallback filter,
+ void *filterUserData, intptr_t n,
+ MlirOperation *slice) {
+ SetVector<Operation *> result;
+ ForwardSliceOptions options;
+ if (filter)
+ options.filter = [filter, filterUserData](Operation *op) {
+ return filter(wrap(op), filterUserData);
+ };
+ getForwardSlice(unwrap(op), &result, options);
+ return copySlice(result, n, slice);
+}
diff --git a/mlir/lib/CAPI/IR/CMakeLists.txt b/mlir/lib/CAPI/IR/CMakeLists.txt
index 8bc76677d2bfd..8cad2cfab9b2c 100644
--- a/mlir/lib/CAPI/IR/CMakeLists.txt
+++ b/mlir/lib/CAPI/IR/CMakeLists.txt
@@ -2,6 +2,7 @@
add_mlir_upstream_c_api_library(MLIRCAPIIR
AffineExpr.cpp
AffineMap.cpp
+ Analysis.cpp
BuiltinAttributes.cpp
BuiltinTypes.cpp
Diagnostics.cpp
@@ -14,6 +15,7 @@ add_mlir_upstream_c_api_library(MLIRCAPIIR
Support.cpp
LINK_LIBS PUBLIC
+ MLIRAnalysis
MLIRBytecodeWriter
MLIRIR
MLIRParser
diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c
index 57ae8b9a2819b..10fbd0a25b659 100644
--- a/mlir/test/CAPI/ir.c
+++ b/mlir/test/CAPI/ir.c
@@ -13,6 +13,7 @@
#include "mlir-c/IR.h"
#include "mlir-c/AffineExpr.h"
#include "mlir-c/AffineMap.h"
+#include "mlir-c/Analysis.h"
#include "mlir-c/BuiltinAttributes.h"
#include "mlir-c/BuiltinTypes.h"
#include "mlir-c/Diagnostics.h"
@@ -2900,6 +2901,77 @@ int testDominanceInfo(MlirContext ctx) {
return 0;
}
+// Prints the names of the operations in a slice buffer, for FileCheck.
+static void printSlice(MlirOperation *slice, intptr_t n) {
+ for (intptr_t i = 0; i < n; ++i) {
+ MlirStringRef name = mlirIdentifierStr(mlirOperationGetName(slice[i]));
+ fprintf(stderr, "slice: %.*s\n", (int)name.length, name.data);
+ }
+}
+
+// Slice filter that treats `arith.subi` as a frontier (stops propagation
+// through it, and excludes it from the slice).
+static bool sliceFilterExcludeSubi(MlirOperation op, void *userData) {
+ (void)userData;
+ MlirStringRef name = mlirIdentifierStr(mlirOperationGetName(op));
+ return !mlirStringRefEqual(name,
+ mlirStringRefCreateFromCString("arith.subi"));
+}
+
+int testForwardSlice(MlirContext ctx) {
+ fprintf(stderr, "@testForwardSlice\n");
+ // CHECK-LABEL: @testForwardSlice
+
+ mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("arith"));
+
+ const char *moduleStr = "func.func @f(%arg0: i32) -> i32 {\n"
+ " %0 = arith.addi %arg0, %arg0 : i32\n"
+ " %1 = arith.muli %0, %arg0 : i32\n"
+ " %2 = arith.subi %1, %0 : i32\n"
+ " return %2 : i32\n"
+ "}\n";
+ MlirModule module =
+ mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(moduleStr));
+
+ MlirBlock moduleBody = mlirModuleGetBody(module);
+ MlirOperation funcOp = mlirBlockGetFirstOperation(moduleBody);
+ MlirRegion funcRegion = mlirOperationGetRegion(funcOp, 0);
+ MlirBlock funcBody = mlirRegionGetFirstBlock(funcRegion);
+ MlirOperation addOp = mlirBlockGetFirstOperation(funcBody);
+
+ // The forward slice of the addi is its transitive users: the muli, the subi
+ // and the return (the addi itself is not included). Query the size first,
+ // then fill a buffer.
+ assert(mlirGetForwardSlice(addOp, NULL, NULL, 0, NULL) == 3);
+ MlirOperation slice[3];
+ intptr_t count = mlirGetForwardSlice(addOp, NULL, NULL, 3, slice);
+ assert(count == 3);
+ fprintf(stderr, "unfiltered forward slice:\n");
+ // CHECK: unfiltered forward slice:
+ printSlice(slice, count);
+ // CHECK-DAG: slice: arith.muli
+ // CHECK-DAG: slice: arith.subi
+ // CHECK-DAG: slice: func.return
+
+ // With a filter that excludes the subi, propagation stops there: only the
+ // muli remains. The return is only reachable through the (excluded) subi, so
+ // it drops out of the slice as well.
+ intptr_t filteredCount =
+ mlirGetForwardSlice(addOp, sliceFilterExcludeSubi, NULL, 3, slice);
+ assert(filteredCount == 1);
+ fprintf(stderr, "filtered forward slice:\n");
+ // CHECK: filtered forward slice:
+ printSlice(slice, filteredCount);
+ // CHECK-NEXT: slice: arith.muli
+ // CHECK-NOT: slice:
+
+ mlirModuleDestroy(module);
+
+ // CHECK: testForwardSlice: PASSED
+ fprintf(stderr, "testForwardSlice: PASSED\n");
+ return 0;
+}
+
int main(void) {
MlirContext ctx = mlirContextCreate();
registerAllUpstreamDialects(ctx);
@@ -2955,6 +3027,8 @@ int main(void) {
return 19;
if (testDominanceInfo(ctx))
return 20;
+ if (testForwardSlice(ctx))
+ return 21;
// CHECK: DESTROY MAIN CONTEXT
// CHECK: reportResourceDelete: resource_i64_blob
>From 88944b6711822f294e80d468228595ea96b80a24 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Mon, 29 Jun 2026 11:00:13 -0700
Subject: [PATCH 2/3] [mlir-c] Add backward slice analysis
---
mlir/include/mlir-c/Analysis.h | 14 ++++++++
mlir/lib/CAPI/IR/Analysis.cpp | 14 ++++++++
mlir/test/CAPI/ir.c | 63 ++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+)
diff --git a/mlir/include/mlir-c/Analysis.h b/mlir/include/mlir-c/Analysis.h
index 8e0da6344b5f8..8d244959a9d6d 100644
--- a/mlir/include/mlir-c/Analysis.h
+++ b/mlir/include/mlir-c/Analysis.h
@@ -37,6 +37,20 @@ MLIR_CAPI_EXPORTED intptr_t mlirGetForwardSlice(MlirOperation op,
void *filterUserData,
intptr_t n, MlirOperation *slice);
+/// Computes the backward slice of the given operation, i.e. all its transitive
+/// definitions, not including the operation itself. The result operations are
+/// written (in slice order) into the caller-allocated `slice` buffer, up to `n`
+/// entries; the total number of operations in the slice is returned. A negative
+/// return value indicates the backward slice could not be computed. Passing
+/// `n == 0` (with `slice` ignored) queries the size. `filter` may be NULL to
+/// traverse all operations; otherwise it acts as a frontier (see
+/// MlirSliceFilterCallback).
+MLIR_CAPI_EXPORTED intptr_t mlirGetBackwardSlice(MlirOperation op,
+ MlirSliceFilterCallback filter,
+ void *filterUserData,
+ intptr_t n,
+ MlirOperation *slice);
+
#ifdef __cplusplus
}
#endif
diff --git a/mlir/lib/CAPI/IR/Analysis.cpp b/mlir/lib/CAPI/IR/Analysis.cpp
index dae2d4e514f3f..a40f6687a78d3 100644
--- a/mlir/lib/CAPI/IR/Analysis.cpp
+++ b/mlir/lib/CAPI/IR/Analysis.cpp
@@ -38,3 +38,17 @@ intptr_t mlirGetForwardSlice(MlirOperation op, MlirSliceFilterCallback filter,
getForwardSlice(unwrap(op), &result, options);
return copySlice(result, n, slice);
}
+
+intptr_t mlirGetBackwardSlice(MlirOperation op, MlirSliceFilterCallback filter,
+ void *filterUserData, intptr_t n,
+ MlirOperation *slice) {
+ SetVector<Operation *> result;
+ BackwardSliceOptions options;
+ if (filter)
+ options.filter = [filter, filterUserData](Operation *op) {
+ return filter(wrap(op), filterUserData);
+ };
+ if (failed(getBackwardSlice(unwrap(op), &result, options)))
+ return -1;
+ return copySlice(result, n, slice);
+}
diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c
index 10fbd0a25b659..7969b6683ac61 100644
--- a/mlir/test/CAPI/ir.c
+++ b/mlir/test/CAPI/ir.c
@@ -2918,6 +2918,14 @@ static bool sliceFilterExcludeSubi(MlirOperation op, void *userData) {
mlirStringRefCreateFromCString("arith.subi"));
}
+// Slice filter that treats `arith.muli` as a frontier.
+static bool sliceFilterExcludeMuli(MlirOperation op, void *userData) {
+ (void)userData;
+ MlirStringRef name = mlirIdentifierStr(mlirOperationGetName(op));
+ return !mlirStringRefEqual(name,
+ mlirStringRefCreateFromCString("arith.muli"));
+}
+
int testForwardSlice(MlirContext ctx) {
fprintf(stderr, "@testForwardSlice\n");
// CHECK-LABEL: @testForwardSlice
@@ -2972,6 +2980,59 @@ int testForwardSlice(MlirContext ctx) {
return 0;
}
+int testBackwardSlice(MlirContext ctx) {
+ fprintf(stderr, "@testBackwardSlice\n");
+ // CHECK-LABEL: @testBackwardSlice
+
+ mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("arith"));
+
+ const char *moduleStr = "func.func @f(%arg0: i32) -> i32 {\n"
+ " %0 = arith.addi %arg0, %arg0 : i32\n"
+ " %1 = arith.muli %0, %arg0 : i32\n"
+ " %2 = arith.subi %1, %0 : i32\n"
+ " return %2 : i32\n"
+ "}\n";
+ MlirModule module =
+ mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(moduleStr));
+
+ MlirBlock moduleBody = mlirModuleGetBody(module);
+ MlirOperation funcOp = mlirBlockGetFirstOperation(moduleBody);
+ MlirRegion funcRegion = mlirOperationGetRegion(funcOp, 0);
+ MlirBlock funcBody = mlirRegionGetFirstBlock(funcRegion);
+ MlirOperation addOp = mlirBlockGetFirstOperation(funcBody);
+ MlirOperation mulOp = mlirOperationGetNextInBlock(addOp);
+ MlirOperation subOp = mlirOperationGetNextInBlock(mulOp);
+
+ // The backward slice of the subi is its transitive definitions: the muli and
+ // the addi (the subi itself is not included; block arguments have no defining
+ // op and are skipped).
+ MlirOperation slice[2];
+ intptr_t count = mlirGetBackwardSlice(subOp, NULL, NULL, 2, slice);
+ assert(count == 2);
+ fprintf(stderr, "unfiltered backward slice:\n");
+ // CHECK: unfiltered backward slice:
+ printSlice(slice, count);
+ // CHECK-DAG: slice: arith.addi
+ // CHECK-DAG: slice: arith.muli
+
+ // With a filter that excludes the muli, propagation stops there. The addi is
+ // still reached directly through the subi's other operand, so it remains.
+ intptr_t filteredCount =
+ mlirGetBackwardSlice(subOp, sliceFilterExcludeMuli, NULL, 2, slice);
+ assert(filteredCount == 1);
+ fprintf(stderr, "filtered backward slice:\n");
+ // CHECK: filtered backward slice:
+ printSlice(slice, filteredCount);
+ // CHECK-NEXT: slice: arith.addi
+ // CHECK-NOT: slice:
+
+ mlirModuleDestroy(module);
+
+ // CHECK: testBackwardSlice: PASSED
+ fprintf(stderr, "testBackwardSlice: PASSED\n");
+ return 0;
+}
+
int main(void) {
MlirContext ctx = mlirContextCreate();
registerAllUpstreamDialects(ctx);
@@ -3029,6 +3090,8 @@ int main(void) {
return 20;
if (testForwardSlice(ctx))
return 21;
+ if (testBackwardSlice(ctx))
+ return 22;
// CHECK: DESTROY MAIN CONTEXT
// CHECK: reportResourceDelete: resource_i64_blob
>From 8a3261bec77b2d7713163400aaa15077b7b30d73 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Mon, 29 Jun 2026 11:02:21 -0700
Subject: [PATCH 3/3] [mlir-c] Add getBlocksSortedByDominance and
topologicalSort
---
mlir/include/mlir-c/Analysis.h | 22 +++++++++-
mlir/lib/CAPI/IR/Analysis.cpp | 20 +++++++++
mlir/test/CAPI/ir.c | 76 ++++++++++++++++++++++++++++++++++
3 files changed, 117 insertions(+), 1 deletion(-)
diff --git a/mlir/include/mlir-c/Analysis.h b/mlir/include/mlir-c/Analysis.h
index 8d244959a9d6d..e0d5c87618180 100644
--- a/mlir/include/mlir-c/Analysis.h
+++ b/mlir/include/mlir-c/Analysis.h
@@ -35,7 +35,8 @@ typedef bool (*MlirSliceFilterCallback)(MlirOperation op, void *userData);
MLIR_CAPI_EXPORTED intptr_t mlirGetForwardSlice(MlirOperation op,
MlirSliceFilterCallback filter,
void *filterUserData,
- intptr_t n, MlirOperation *slice);
+ intptr_t n,
+ MlirOperation *slice);
/// Computes the backward slice of the given operation, i.e. all its transitive
/// definitions, not including the operation itself. The result operations are
@@ -51,6 +52,25 @@ MLIR_CAPI_EXPORTED intptr_t mlirGetBackwardSlice(MlirOperation op,
intptr_t n,
MlirOperation *slice);
+//===----------------------------------------------------------------------===//
+// Topological sort
+//===----------------------------------------------------------------------===//
+
+/// Returns the blocks of the given region sorted by dominance, a stable order
+/// in which a block appears after all blocks that dominate it. The result
+/// blocks are written into the caller-allocated `blocks` buffer, up to `n`
+/// entries; the total number of blocks in the region is returned. Passing
+/// `n == 0` (with `blocks` ignored) queries the size.
+MLIR_CAPI_EXPORTED intptr_t mlirRegionGetBlocksSortedByDominance(
+ MlirRegion region, intptr_t n, MlirBlock *blocks);
+
+/// Topologically sorts the `nOps` operations in `ops` (taking region semantics
+/// into account) so that definitions come before uses, writing the result into
+/// the caller-allocated `sorted` buffer, which must have room for `nOps`
+/// entries. The input operations need not all belong to the same block.
+MLIR_CAPI_EXPORTED void mlirTopologicalSort(intptr_t nOps, MlirOperation *ops,
+ MlirOperation *sorted);
+
#ifdef __cplusplus
}
#endif
diff --git a/mlir/lib/CAPI/IR/Analysis.cpp b/mlir/lib/CAPI/IR/Analysis.cpp
index a40f6687a78d3..2d59566ff22b4 100644
--- a/mlir/lib/CAPI/IR/Analysis.cpp
+++ b/mlir/lib/CAPI/IR/Analysis.cpp
@@ -9,6 +9,7 @@
#include "mlir-c/Analysis.h"
#include "mlir/Analysis/SliceAnalysis.h"
+#include "mlir/Analysis/TopologicalSortUtils.h"
#include "mlir/CAPI/IR.h"
#include "mlir/CAPI/Support.h"
@@ -52,3 +53,22 @@ intptr_t mlirGetBackwardSlice(MlirOperation op, MlirSliceFilterCallback filter,
return -1;
return copySlice(result, n, slice);
}
+
+intptr_t mlirRegionGetBlocksSortedByDominance(MlirRegion region, intptr_t n,
+ MlirBlock *blocks) {
+ SetVector<Block *> sorted = getBlocksSortedByDominance(*unwrap(region));
+ intptr_t count = static_cast<intptr_t>(sorted.size());
+ for (intptr_t i = 0, e = std::min(count, n); i < e; ++i)
+ blocks[i] = wrap(sorted[i]);
+ return count;
+}
+
+void mlirTopologicalSort(intptr_t nOps, MlirOperation *ops,
+ MlirOperation *sorted) {
+ SetVector<Operation *> toSort;
+ for (intptr_t i = 0; i < nOps; ++i)
+ toSort.insert(unwrap(ops[i]));
+ SetVector<Operation *> result = topologicalSort(toSort);
+ for (intptr_t i = 0, e = static_cast<intptr_t>(result.size()); i < e; ++i)
+ sorted[i] = wrap(result[i]);
+}
diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c
index 7969b6683ac61..dbb67dc91d3f3 100644
--- a/mlir/test/CAPI/ir.c
+++ b/mlir/test/CAPI/ir.c
@@ -3033,6 +3033,80 @@ int testBackwardSlice(MlirContext ctx) {
return 0;
}
+int testTopologicalSort(MlirContext ctx) {
+ fprintf(stderr, "@testTopologicalSort\n");
+ // CHECK-LABEL: @testTopologicalSort
+
+ mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("arith"));
+ mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("cf"));
+
+ // Blocks sorted by dominance: the entry block dominates all others and must
+ // come first; the merge block ^bb3 comes last.
+ const char *cfgStr = "func.func @g(%cond: i1) -> i32 {\n"
+ " %c0 = arith.constant 0 : i32\n"
+ " %c1 = arith.constant 1 : i32\n"
+ " cf.cond_br %cond, ^bb1, ^bb2\n"
+ "^bb1:\n"
+ " cf.br ^bb3(%c0 : i32)\n"
+ "^bb2:\n"
+ " cf.br ^bb3(%c1 : i32)\n"
+ "^bb3(%result: i32):\n"
+ " return %result : i32\n"
+ "}\n";
+ MlirModule cfgModule =
+ mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(cfgStr));
+ MlirBlock cfgModuleBody = mlirModuleGetBody(cfgModule);
+ MlirOperation gFuncOp = mlirBlockGetFirstOperation(cfgModuleBody);
+ MlirRegion gRegion = mlirOperationGetRegion(gFuncOp, 0);
+ MlirBlock entry = mlirRegionGetFirstBlock(gRegion);
+ MlirBlock bb3 = mlirBlockGetNextInRegion(
+ mlirBlockGetNextInRegion(mlirBlockGetNextInRegion(entry)));
+
+ MlirBlock blocks[4];
+ intptr_t numBlocks = mlirRegionGetBlocksSortedByDominance(gRegion, 4, blocks);
+ assert(numBlocks == 4);
+ // The entry block dominates everything (reported first); the merge block is
+ // dominated by the entry (reported last).
+ assert(mlirBlockEqual(blocks[0], entry));
+ assert(mlirBlockEqual(blocks[3], bb3));
+
+ mlirModuleDestroy(cfgModule);
+
+ // Topological sort of a set of operations passed in reverse program order.
+ const char *chainStr = "func.func @f(%arg0: i32) -> i32 {\n"
+ " %0 = arith.addi %arg0, %arg0 : i32\n"
+ " %1 = arith.muli %0, %arg0 : i32\n"
+ " %2 = arith.subi %1, %0 : i32\n"
+ " return %2 : i32\n"
+ "}\n";
+ MlirModule chainModule =
+ mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(chainStr));
+ MlirBlock chainModuleBody = mlirModuleGetBody(chainModule);
+ MlirOperation fFuncOp = mlirBlockGetFirstOperation(chainModuleBody);
+ MlirRegion fRegion = mlirOperationGetRegion(fFuncOp, 0);
+ MlirBlock fBody = mlirRegionGetFirstBlock(fRegion);
+ MlirOperation addOp = mlirBlockGetFirstOperation(fBody);
+ MlirOperation mulOp = mlirOperationGetNextInBlock(addOp);
+ MlirOperation subOp = mlirOperationGetNextInBlock(mulOp);
+
+ // Pass them reversed; the sort must restore defs-before-uses order.
+ MlirOperation unsorted[3] = {subOp, mulOp, addOp};
+ MlirOperation sorted[3];
+ mlirTopologicalSort(3, unsorted, sorted);
+ fprintf(stderr, "topo sort:\n");
+ // CHECK: topo sort:
+ printSlice(sorted, 3);
+ // CHECK-NEXT: slice: arith.addi
+ // CHECK-NEXT: slice: arith.muli
+ // CHECK-NEXT: slice: arith.subi
+
+ mlirModuleDestroy(chainModule);
+
+ // CHECK: testTopologicalSort: PASSED
+ fprintf(stderr, "testTopologicalSort: PASSED\n");
+ return 0;
+}
+
int main(void) {
MlirContext ctx = mlirContextCreate();
registerAllUpstreamDialects(ctx);
@@ -3092,6 +3166,8 @@ int main(void) {
return 21;
if (testBackwardSlice(ctx))
return 22;
+ if (testTopologicalSort(ctx))
+ return 23;
// CHECK: DESTROY MAIN CONTEXT
// CHECK: reportResourceDelete: resource_i64_blob
More information about the Mlir-commits
mailing list