#include "mlir/Analysis/SliceWalk.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
using namespace mlir;
WalkContinuation mlir::walkSlice(ValueRange rootValues,
WalkCallback walkCallback) {
SmallVector<Value> workList = rootValues;
llvm::SmallDenseSet<Value, 16> seenValues;
while (!workList.empty()) {
Value current = workList.pop_back_val();
if (!seenValues.insert(current).second)
continue;
WalkContinuation continuation = walkCallback(current);
if (continuation.wasInterrupted())
return continuation;
if (continuation.wasSkipped())
continue;
assert(continuation.wasAdvancedTo());
workList.append(continuation.getNextValues().begin(),
continuation.getNextValues().end());
}
return WalkContinuation::skip();
}
static SmallVector<Value>
getRegionPredecessorOperands(RegionBranchOpInterface regionOp,
RegionSuccessor successor,
unsigned operandNumber) {
SmallVector<Value> predecessorOperands;
auto isContained = [](ArrayRef<RegionSuccessor> successors,
RegionSuccessor successor) {
auto *it = llvm::find_if(successors, [&successor](RegionSuccessor curr) {
return curr.getSuccessor() == successor.getSuccessor();
});
return it != successors.end();
};
SmallVector<Attribute> operandAttributes(regionOp->getNumOperands());
SmallVector<RegionSuccessor> successors;
regionOp.getEntrySuccessorRegions(operandAttributes, successors);
if (isContained(successors, successor)) {
OperandRange operands = regionOp.getEntrySuccessorOperands(successor);
predecessorOperands.push_back(operands[operandNumber]);
}
for (Region ®ion : regionOp->getRegions()) {
for (Block &block : region) {
auto terminatorOp =
dyn_cast<RegionBranchTerminatorOpInterface>(block.getTerminator());
if (!terminatorOp)
continue;
SmallVector<Attribute> operandAttributes(terminatorOp->getNumOperands());
SmallVector<RegionSuccessor> successors;
terminatorOp.getSuccessorRegions(operandAttributes, successors);
if (isContained(successors, successor)) {
OperandRange operands = terminatorOp.getSuccessorOperands(successor);
predecessorOperands.push_back(operands[operandNumber]);
}
}
}
return predecessorOperands;
}
static std::optional<SmallVector<Value>>
getBlockPredecessorOperands(BlockArgument blockArg) {
Block *block = blockArg.getOwner();
SmallVector<Value> predecessorOperands;
for (auto it = block->pred_begin(); it != block->pred_end(); ++it) {
Block *predecessor = *it;
auto branchOp = dyn_cast<BranchOpInterface>(predecessor->getTerminator());
if (!branchOp)
return std::nullopt;
SuccessorOperands successorOperands =
branchOp.getSuccessorOperands(it.getSuccessorIndex());
if (Value operand = successorOperands[blockArg.getArgNumber()])
predecessorOperands.push_back(operand);
}
return predecessorOperands;
}
std::optional<SmallVector<Value>>
mlir::getControlFlowPredecessors(Value value) {
if (OpResult opResult = dyn_cast<OpResult>(value)) {
if (auto selectOp = opResult.getDefiningOp<SelectLikeOpInterface>())
return SmallVector<Value>(
{selectOp.getTrueValue(), selectOp.getFalseValue()});
auto regionOp = opResult.getDefiningOp<RegionBranchOpInterface>();
if (!regionOp)
return std::nullopt;
RegionSuccessor region(regionOp, regionOp->getResults());
SmallVector<Value> predecessorOperands = getRegionPredecessorOperands(
regionOp, region, opResult.getResultNumber());
return predecessorOperands;
}
auto blockArg = cast<BlockArgument>(value);
Block *block = blockArg.getOwner();
if (block->isEntryBlock()) {
if (auto regionBranchOp =
dyn_cast<RegionBranchOpInterface>(block->getParentOp())) {
RegionSuccessor region(blockArg.getParentRegion());
SmallVector<Value> predecessorOperands = getRegionPredecessorOperands(
regionBranchOp, region, blockArg.getArgNumber());
return predecessorOperands;
}
return std::nullopt;
}
return getBlockPredecessorOperands(blockArg);
}