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.
71 RegionSuccessor region = RegionSuccessor(regionOp.getOperation());
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:306
unsigned getArgNumber() const
Returns the number of this argument.
Definition Value.h:318
Block * getOwner() const
Returns the block that owns this argument.
Definition Value.h:315
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:454
This class represents a successor of a region.
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:389
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