3
3
4
4
using namespace mlir ;
5
5
6
+ WalkContinuation mlir::walkSlice (ValueRange rootValues,
7
+ WalkCallback walkCallback) {
8
+ // Search the backward slice starting from the root values.
9
+ SmallVector<Value> workList = rootValues;
10
+ llvm::SmallDenseSet<Value, 16 > seenValues;
11
+ while (!workList.empty ()) {
12
+ // Search the backward slice of the current value.
13
+ Value current = workList.pop_back_val ();
14
+
15
+ // Skip the current value if it has already been seen.
16
+ if (!seenValues.insert (current).second )
17
+ continue ;
18
+
19
+ // Call the walk callback with the current value.
20
+ WalkContinuation continuation = walkCallback (current);
21
+ if (continuation.wasInterrupted ())
22
+ return continuation;
23
+ if (continuation.wasSkipped ())
24
+ continue ;
25
+
26
+ assert (continuation.wasAdvancedTo ());
27
+ // Add the next values to the work list if the walk should continue.
28
+ workList.append (continuation.getNextValues ().begin (),
29
+ continuation.getNextValues ().end ());
30
+ }
31
+
32
+ return WalkContinuation::skip ();
33
+ }
34
+
6
35
// / Returns the operands from all predecessor regions that match `operandNumber`
7
36
// / for the `successor` region within `regionOp`.
8
37
static SmallVector<Value>
@@ -49,15 +78,20 @@ getRegionPredecessorOperands(RegionBranchOpInterface regionOp,
49
78
return predecessorOperands;
50
79
}
51
80
52
- // / Returns the predecessor branch operands that match `blockArg`.
53
- static SmallVector<Value> getBlockPredecessorOperands (BlockArgument blockArg) {
81
+ // / Returns the predecessor branch operands that match `blockArg`. Returns a
82
+ // / nullopt when some of the predecessor terminators do not implement the
83
+ // / BranchOpInterface.
84
+ static std::optional<SmallVector<Value>>
85
+ getBlockPredecessorOperands (BlockArgument blockArg) {
54
86
Block *block = blockArg.getOwner ();
55
87
56
88
// Search the predecessor operands for all predecessor terminators.
57
89
SmallVector<Value> predecessorOperands;
58
90
for (auto it = block->pred_begin (); it != block->pred_end (); ++it) {
59
91
Block *predecessor = *it;
60
- auto branchOp = cast<BranchOpInterface>(predecessor->getTerminator ());
92
+ auto branchOp = dyn_cast<BranchOpInterface>(predecessor->getTerminator ());
93
+ if (!branchOp)
94
+ return std::nullopt;
61
95
SuccessorOperands successorOperands =
62
96
branchOp.getSuccessorOperands (it.getSuccessorIndex ());
63
97
// Store the predecessor operand if the block argument matches an operand
@@ -69,62 +103,38 @@ static SmallVector<Value> getBlockPredecessorOperands(BlockArgument blockArg) {
69
103
return predecessorOperands;
70
104
}
71
105
72
- mlir::WalkContinuation mlir::walkBackwardSlice (ValueRange rootValues,
73
- WalkCallback walkCallback) {
74
- // Search the backward slice starting from the root values.
75
- SmallVector<Value> workList = rootValues;
76
- llvm::SmallDenseSet<Value, 16 > seenValues;
77
- while (!workList.empty ()) {
78
- // Search the backward slice of the current value.
79
- Value current = workList.pop_back_val ();
80
-
81
- // Skip the current value if it has already been seen.
82
- if (!seenValues.insert (current).second )
83
- continue ;
84
-
85
- // Call the walk callback with the current value.
86
- WalkContinuation continuation = walkCallback (current);
87
- if (continuation.wasInterrupted ())
88
- return continuation;
89
- if (continuation.wasSkipped ())
90
- continue ;
91
-
92
- // Add the next values to the work list if the walk should continue.
93
- if (continuation.wasAdvancedTo ()) {
94
- workList.append (continuation.getNextValues ().begin (),
95
- continuation.getNextValues ().end ());
96
- continue ;
97
- }
98
-
106
+ std::optional<SmallVector<Value>>
107
+ mlir::getControlFlowPredecessors (Value value) {
108
+ SmallVector<Value> result;
109
+ if (OpResult opResult = dyn_cast<OpResult>(value)) {
110
+ auto regionOp = dyn_cast<RegionBranchOpInterface>(opResult.getOwner ());
111
+ // If the interface is not implemented, there are no control flow
112
+ // predecessors to work with.
113
+ if (!regionOp)
114
+ return std::nullopt;
99
115
// Add the control flow predecessor operands to the work list.
100
- if (OpResult opResult = dyn_cast<OpResult>(current)) {
101
- auto regionOp = dyn_cast<RegionBranchOpInterface>(opResult.getOwner ());
102
- if (!regionOp)
103
- continue ;
104
- RegionSuccessor region (regionOp->getResults ());
105
- SmallVector<Value> predecessorOperands = getRegionPredecessorOperands (
106
- regionOp, region, opResult.getResultNumber ());
107
- workList.append (predecessorOperands.begin (), predecessorOperands.end ());
108
- continue ;
109
- }
116
+ RegionSuccessor region (regionOp->getResults ());
117
+ SmallVector<Value> predecessorOperands = getRegionPredecessorOperands (
118
+ regionOp, region, opResult.getResultNumber ());
119
+ return predecessorOperands;
120
+ }
110
121
111
- auto blockArg = cast<BlockArgument>(current );
112
- Block *block = blockArg.getOwner ();
113
- // Search the region predecessor operands for structured control flow.
114
- auto regionBranchOp =
115
- dyn_cast<RegionBranchOpInterface>(block-> getParentOp ());
116
- if (block->isEntryBlock () && regionBranchOp ) {
122
+ auto blockArg = cast<BlockArgument>(value );
123
+ Block *block = blockArg.getOwner ();
124
+ // Search the region predecessor operands for structured control flow.
125
+ if (block-> isEntryBlock ()) {
126
+ if ( auto regionBranchOp =
127
+ dyn_cast<RegionBranchOpInterface> (block->getParentOp ()) ) {
117
128
RegionSuccessor region (blockArg.getParentRegion ());
118
129
SmallVector<Value> predecessorOperands = getRegionPredecessorOperands (
119
130
regionBranchOp, region, blockArg.getArgNumber ());
120
- workList.append (predecessorOperands.begin (), predecessorOperands.end ());
121
- continue ;
131
+ return predecessorOperands;
122
132
}
123
- // Search the block predecessor operands for unstructured control flow.
124
- SmallVector<Value> predecessorOperands =
125
- getBlockPredecessorOperands (blockArg);
126
- workList.append (predecessorOperands.begin (), predecessorOperands.end ());
133
+ // Unclear how to deal with this operation, conservatively return a
134
+ // failure.
135
+ return std::nullopt;
127
136
}
128
137
129
- return WalkContinuation::advance ();
138
+ // Search the block predecessor operands for unstructured control flow.
139
+ return getBlockPredecessorOperands (blockArg);
130
140
}
0 commit comments