@@ -41,11 +41,27 @@ getForwardSliceImpl(Operation *op, DenseSet<Operation *> &visited,
41
41
for (Region ®ion : op->getRegions ())
42
42
for (Block &block : region)
43
43
for (Operation &blockOp : block)
44
- if (forwardSlice->count (&blockOp) == 0 )
44
+ if (forwardSlice->count (&blockOp) == 0 ) {
45
+ // We don't have to check if the 'blockOp' is already visited because
46
+ // there cannot be a traversal path from this nested op to the parent
47
+ // and thus a cycle cannot be closed here. We still have to mark it
48
+ // as visited to stop before visiting this operation again if it is
49
+ // part of a cycle.
50
+ visited.insert (&blockOp);
45
51
getForwardSliceImpl (&blockOp, visited, forwardSlice, filter);
52
+ visited.erase (&blockOp);
53
+ }
46
54
47
55
for (Value result : op->getResults ())
48
56
for (Operation *userOp : result.getUsers ()) {
57
+ // A cycle can only occur within a basic block (not across regions or
58
+ // basic blocks) because the parent region must be a graph region, graph
59
+ // regions are restricted to always have 0 or 1 blocks, and there cannot
60
+ // be a def-use edge from a nested operation to an operation in an
61
+ // ancestor region. Therefore, we don't have to but may use the same
62
+ // 'visited' set across regions/blocks as long as we remove operations
63
+ // from the set again when the DFS traverses back from the leaf to the
64
+ // root.
49
65
if (forwardSlice->count (userOp) == 0 && visited.insert (userOp).second )
50
66
getForwardSliceImpl (userOp, visited, forwardSlice, filter);
51
67
@@ -58,6 +74,7 @@ getForwardSliceImpl(Operation *op, DenseSet<Operation *> &visited,
58
74
void mlir::getForwardSlice (Operation *op, SetVector<Operation *> *forwardSlice,
59
75
const ForwardSliceOptions &options) {
60
76
DenseSet<Operation *> visited;
77
+ visited.insert (op);
61
78
getForwardSliceImpl (op, visited, forwardSlice, options.filter );
62
79
if (!options.inclusive ) {
63
80
// Don't insert the top level operation, we just queried on it and don't
@@ -75,8 +92,11 @@ void mlir::getForwardSlice(Operation *op, SetVector<Operation *> *forwardSlice,
75
92
void mlir::getForwardSlice (Value root, SetVector<Operation *> *forwardSlice,
76
93
const SliceOptions &options) {
77
94
DenseSet<Operation *> visited;
78
- for (Operation *user : root.getUsers ())
95
+ for (Operation *user : root.getUsers ()) {
96
+ visited.insert (user);
79
97
getForwardSliceImpl (user, visited, forwardSlice, options.filter );
98
+ visited.erase (user);
99
+ }
80
100
81
101
// Reverse to get back the actual topological order.
82
102
// std::reverse does not work out of the box on SetVector and I want an
@@ -158,6 +178,7 @@ LogicalResult mlir::getBackwardSlice(Operation *op,
158
178
SetVector<Operation *> *backwardSlice,
159
179
const BackwardSliceOptions &options) {
160
180
DenseSet<Operation *> visited;
181
+ visited.insert (op);
161
182
LogicalResult result =
162
183
getBackwardSliceImpl (op, visited, backwardSlice, options);
163
184
0 commit comments