MLIR 22.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 operands from all predecessor regions that match `operandNumber`
36/// for the `successor` region within `regionOp`.
38getRegionPredecessorOperands(RegionBranchOpInterface regionOp,
39 RegionSuccessor successor,
40 unsigned operandNumber) {
41 SmallVector<Value> predecessorOperands;
42
43 // Returns true if `successors` contains `successor`.
44 auto isContained = [](ArrayRef<RegionSuccessor> successors,
45 RegionSuccessor successor) {
46 auto *it = llvm::find_if(successors, [&successor](RegionSuccessor curr) {
47 return curr.getSuccessor() == successor.getSuccessor();
48 });
49 return it != successors.end();
50 };
51
52 // Search the operand ranges on the region operation itself.
53 SmallVector<Attribute> operandAttributes(regionOp->getNumOperands());
55 regionOp.getEntrySuccessorRegions(operandAttributes, successors);
56 if (isContained(successors, successor)) {
57 OperandRange operands = regionOp.getEntrySuccessorOperands(successor);
58 predecessorOperands.push_back(operands[operandNumber]);
59 }
60
61 // Search the operand ranges on region terminators.
62 for (Region &region : regionOp->getRegions()) {
63 for (Block &block : region) {
64 auto terminatorOp =
65 dyn_cast<RegionBranchTerminatorOpInterface>(block.getTerminator());
66 if (!terminatorOp)
67 continue;
68 SmallVector<Attribute> operandAttributes(terminatorOp->getNumOperands());
70 terminatorOp.getSuccessorRegions(operandAttributes, successors);
71 if (isContained(successors, successor)) {
72 OperandRange operands = terminatorOp.getSuccessorOperands(successor);
73 predecessorOperands.push_back(operands[operandNumber]);
74 }
75 }
76 }
77
78 return predecessorOperands;
79}
80
81/// Returns the predecessor branch operands that match `blockArg`, or nullopt if
82/// some of the predecessor terminators do not implement the BranchOpInterface.
83static std::optional<SmallVector<Value>>
85 Block *block = blockArg.getOwner();
86
87 // Search the predecessor operands for all predecessor terminators.
88 SmallVector<Value> predecessorOperands;
89 for (auto it = block->pred_begin(); it != block->pred_end(); ++it) {
90 Block *predecessor = *it;
91 auto branchOp = dyn_cast<BranchOpInterface>(predecessor->getTerminator());
92 if (!branchOp)
93 return std::nullopt;
94 SuccessorOperands successorOperands =
95 branchOp.getSuccessorOperands(it.getSuccessorIndex());
96 // Store the predecessor operand if the block argument matches an operand
97 // and is not produced by the terminator.
98 if (Value operand = successorOperands[blockArg.getArgNumber()])
99 predecessorOperands.push_back(operand);
100 }
101
102 return predecessorOperands;
103}
104
105std::optional<SmallVector<Value>>
107 if (OpResult opResult = dyn_cast<OpResult>(value)) {
108 if (auto selectOp = opResult.getDefiningOp<SelectLikeOpInterface>())
109 return SmallVector<Value>(
110 {selectOp.getTrueValue(), selectOp.getFalseValue()});
111 auto regionOp = opResult.getDefiningOp<RegionBranchOpInterface>();
112 // If the interface is not implemented, there are no control flow
113 // predecessors to work with.
114 if (!regionOp)
115 return std::nullopt;
116 // Add the control flow predecessor operands to the work list.
117 RegionSuccessor region(regionOp, regionOp->getResults());
119 regionOp, region, opResult.getResultNumber());
120 return predecessorOperands;
121 }
122
123 auto blockArg = cast<BlockArgument>(value);
124 Block *block = blockArg.getOwner();
125 // Search the region predecessor operands for structured control flow.
126 if (block->isEntryBlock()) {
127 if (auto regionBranchOp =
128 dyn_cast<RegionBranchOpInterface>(block->getParentOp())) {
129 RegionSuccessor region(blockArg.getParentRegion());
131 regionBranchOp, region, blockArg.getArgNumber());
132 return predecessorOperands;
133 }
134 // If the interface is not implemented, there are no control flow
135 // predecessors to work with.
136 return std::nullopt;
137 }
138
139 // Search the block predecessor operands for unstructured control flow.
140 return getBlockPredecessorOperands(blockArg);
141}
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:84
static SmallVector< Value > getRegionPredecessorOperands(RegionBranchOpInterface regionOp, RegionSuccessor successor, unsigned operandNumber)
Returns the operands from all predecessor regions that match operandNumber for the successor region w...
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:236
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:244
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:239
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 implements the operand iterators for the Operation class.
Definition ValueRange.h:43
This class represents a successor of a region.
Region * getSuccessor() const
Return the given region successor.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
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.
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