MLIR 23.0.0git
SliceWalk.cpp
Go to the documentation of this file.
3
4using namespace mlir;
5
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
33}
34
35/// Returns the predecessor branch operands that match `blockArg`, or nullopt if
36/// some of the predecessor terminators do not implement the BranchOpInterface.
37static std::optional<SmallVector<Value>>
39 Block *block = blockArg.getOwner();
40
41 // Search the predecessor operands for all predecessor terminators.
42 SmallVector<Value> predecessorOperands;
43 for (auto it = block->pred_begin(); it != block->pred_end(); ++it) {
44 Block *predecessor = *it;
45 auto branchOp = dyn_cast<BranchOpInterface>(predecessor->getTerminator());
46 if (!branchOp)
47 return std::nullopt;
48 SuccessorOperands successorOperands =
49 branchOp.getSuccessorOperands(it.getSuccessorIndex());
50 // Store the predecessor operand if the block argument matches an operand
51 // and is not produced by the terminator.
52 if (Value operand = successorOperands[blockArg.getArgNumber()])
53 predecessorOperands.push_back(operand);
54 }
55
56 return predecessorOperands;
57}
58
59std::optional<SmallVector<Value>>
61 if (OpResult opResult = dyn_cast<OpResult>(value)) {
62 if (auto selectOp = opResult.getDefiningOp<SelectLikeOpInterface>())
63 return SmallVector<Value>(
64 {selectOp.getTrueValue(), selectOp.getFalseValue()});
65 auto regionOp = opResult.getDefiningOp<RegionBranchOpInterface>();
66 // If the interface is not implemented, there are no control flow
67 // predecessors to work with.
68 if (!regionOp)
69 return std::nullopt;
70 // Add the control flow predecessor operands to the work list.
72 SmallVector<Value> predecessorOperands;
73 // TODO (#175168): This assumes that there are no non-successor-inputs
74 // in front of the op result.
75 regionOp.getPredecessorValues(region, opResult.getResultNumber(),
76 predecessorOperands);
77 return predecessorOperands;
78 }
79
80 auto blockArg = cast<BlockArgument>(value);
81 Block *block = blockArg.getOwner();
82 // Search the region predecessor operands for structured control flow.
83 if (block->isEntryBlock()) {
84 if (auto regionBranchOp =
85 dyn_cast<RegionBranchOpInterface>(block->getParentOp())) {
86 RegionSuccessor region(blockArg.getParentRegion());
87 SmallVector<Value> predecessorOperands;
88 // TODO (#175168): This assumes that there are no non-successor-inputs
89 // in front of the block argument.
90 regionBranchOp.getPredecessorValues(region, blockArg.getArgNumber(),
91 predecessorOperands);
92 return predecessorOperands;
93 }
94 // If the interface is not implemented, there are no control flow
95 // predecessors to work with.
96 return std::nullopt;
97 }
98
99 // Search the block predecessor operands for unstructured control flow.
100 return getBlockPredecessorOperands(blockArg);
101}
static std::optional< SmallVector< Value > > getBlockPredecessorOperands(BlockArgument blockArg)
Returns the predecessor branch operands that match blockArg, or nullopt if some of the predecessor te...
Definition SliceWalk.cpp:38
This class represents an argument of a Block.
Definition Value.h:309
unsigned getArgNumber() const
Returns the number of this argument.
Definition Value.h:321
Block * getOwner() const
Returns the block that owns this argument.
Definition Value.h:318
Block represents an ordered list of Operations.
Definition Block.h:33
pred_iterator pred_begin()
Definition Block.h:246
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:249
bool isEntryBlock()
Return if this block is the entry block in the parent region.
Definition Block.cpp:36
pred_iterator pred_end()
Definition Block.h:249
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition Block.cpp:31
This is a value defined by a result of an operation.
Definition Value.h:457
This class represents a successor of a region.
static RegionSuccessor parent()
Initialize a successor that branches after/out of the parent operation.
This class models how operands are forwarded to block arguments in control flow.
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:387
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
A class to signal how to proceed with the walk of the backward slice:
Definition SliceWalk.h:20
bool wasInterrupted() const
Returns true if the walk was interrupted.
Definition SliceWalk.h:60
bool wasAdvancedTo() const
Returns true if the walk was advanced to user-specified values.
Definition SliceWalk.h:66
static WalkContinuation skip()
Creates a continuation that advances the walk without adding any predecessor values to the work list.
Definition SliceWalk.h:55
mlir::ArrayRef< mlir::Value > getNextValues() const
Returns the next values to continue the walk with.
Definition SliceWalk.h:69
bool wasSkipped() const
Returns true if the walk was skipped.
Definition SliceWalk.h:63
Include the generated interface declarations.
std::optional< SmallVector< Value > > getControlFlowPredecessors(Value value)
Computes a vector of all control predecessors of value.
Definition SliceWalk.cpp:60
WalkContinuation walkSlice(mlir::ValueRange rootValues, WalkCallback walkCallback)
Walks the slice starting from the rootValues using a depth-first traversal.
Definition SliceWalk.cpp:6
mlir::function_ref< WalkContinuation(mlir::Value)> WalkCallback
A callback that is invoked for each value encountered during the walk of the slice.
Definition SliceWalk.h:81