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