Skip to content

Commit 08a424a

Browse files
committed
Patch dataflow framework
It had a bug whereby the regions of an op are marked as dead code, and their successors are not properly populated, if any operand of a RegionBranchOpInterface is not folded to a constant. The interface already is meant to support partially-folded operands, so we should use that instead of giving up. Some changes are also just to make debug prints more helpful. Some of them were printing pointer addresses.
1 parent 5fc954d commit 08a424a

File tree

3 files changed

+30
-16
lines changed

3 files changed

+30
-16
lines changed

mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ class DeadCodeAnalysis : public DataFlowAnalysis {
223223
/// Get the constant values of the operands of the operation. Returns
224224
/// std::nullopt if any of the operand lattices are uninitialized.
225225
std::optional<SmallVector<Attribute>> getOperandValues(Operation *op);
226+
227+
/// Get the constant values of the operands of the operation.
228+
/// If the operand lattices are uninitialized, add a null attribute for those.
229+
SmallVector<Attribute> getOperandValuesBestEffort(Operation *op);
226230

227231
/// The top-level operation the analysis is running on. This is used to detect
228232
/// if a callable is outside the scope of the analysis and thus must be

mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -341,23 +341,37 @@ void DeadCodeAnalysis::visitCallOperation(CallOpInterface call) {
341341
/// constant value lattices are uninitialized, return std::nullopt to indicate
342342
/// the analysis should bail out.
343343
static std::optional<SmallVector<Attribute>> getOperandValuesImpl(
344-
Operation *op,
344+
Operation *op, bool failIfAnyNull,
345345
function_ref<const Lattice<ConstantValue> *(Value)> getLattice) {
346346
SmallVector<Attribute> operands;
347347
operands.reserve(op->getNumOperands());
348348
for (Value operand : op->getOperands()) {
349349
const Lattice<ConstantValue> *cv = getLattice(operand);
350350
// If any of the operands' values are uninitialized, bail out.
351-
if (cv->getValue().isUninitialized())
352-
return {};
351+
if (cv->getValue().isUninitialized()) {
352+
if (failIfAnyNull)
353+
return {};
354+
operands.emplace_back();
355+
continue;
356+
}
357+
353358
operands.push_back(cv->getValue().getConstantValue());
354359
}
355360
return operands;
356361
}
357362

358363
std::optional<SmallVector<Attribute>>
359364
DeadCodeAnalysis::getOperandValues(Operation *op) {
360-
return getOperandValuesImpl(op, [&](Value value) {
365+
return getOperandValuesImpl(op, true, [&](Value value) {
366+
auto *lattice = getOrCreate<Lattice<ConstantValue>>(value);
367+
lattice->useDefSubscribe(this);
368+
return lattice;
369+
});
370+
}
371+
372+
SmallVector<Attribute>
373+
DeadCodeAnalysis::getOperandValuesBestEffort(Operation *op) {
374+
return *getOperandValuesImpl(op, false, [&](Value value) {
361375
auto *lattice = getOrCreate<Lattice<ConstantValue>>(value);
362376
lattice->useDefSubscribe(this);
363377
return lattice;
@@ -366,11 +380,9 @@ DeadCodeAnalysis::getOperandValues(Operation *op) {
366380

367381
void DeadCodeAnalysis::visitBranchOperation(BranchOpInterface branch) {
368382
// Try to deduce a single successor for the branch.
369-
std::optional<SmallVector<Attribute>> operands = getOperandValues(branch);
370-
if (!operands)
371-
return;
383+
SmallVector<Attribute> operands = getOperandValuesBestEffort(branch);
372384

373-
if (Block *successor = branch.getSuccessorForOperands(*operands)) {
385+
if (Block *successor = branch.getSuccessorForOperands(operands)) {
374386
markEdgeLive(branch->getBlock(), successor);
375387
} else {
376388
// Otherwise, mark all successors as executable and outgoing edges.
@@ -382,12 +394,10 @@ void DeadCodeAnalysis::visitBranchOperation(BranchOpInterface branch) {
382394
void DeadCodeAnalysis::visitRegionBranchOperation(
383395
RegionBranchOpInterface branch) {
384396
// Try to deduce which regions are executable.
385-
std::optional<SmallVector<Attribute>> operands = getOperandValues(branch);
386-
if (!operands)
387-
return;
397+
SmallVector<Attribute> operands = getOperandValuesBestEffort(branch);
388398

389399
SmallVector<RegionSuccessor> successors;
390-
branch.getEntrySuccessorRegions(*operands, successors);
400+
branch.getEntrySuccessorRegions(operands, successors);
391401
for (const RegionSuccessor &successor : successors) {
392402
// The successor can be either an entry block or the parent operation.
393403
ProgramPoint *point =

mlir/lib/Analysis/DataFlowFramework.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ void AnalysisState::addDependency(ProgramPoint *dependent,
4444
(void)inserted;
4545
DATAFLOW_DEBUG({
4646
if (inserted) {
47-
llvm::dbgs() << "Creating dependency between " << debugName << " of "
48-
<< anchor << "\nand " << debugName << " on " << dependent
49-
<< "\n";
47+
llvm::dbgs() << "Creating dependency between \t" << debugName << " of "
48+
<< anchor << "\n and\t" << debugName
49+
<< " of " << *dependent << "\n";
5050
}
5151
});
5252
}
@@ -125,7 +125,7 @@ LogicalResult DataFlowSolver::initializeAndRun(Operation *top) {
125125
worklist.pop();
126126

127127
DATAFLOW_DEBUG(llvm::dbgs() << "Invoking '" << analysis->debugName
128-
<< "' on: " << point << "\n");
128+
<< "' on: " << *point << "\n");
129129
if (failed(analysis->visit(point)))
130130
return failure();
131131
}

0 commit comments

Comments
 (0)