Skip to content

Commit 61ad087

Browse files
authored
[MLIR][Affine] NFC. Fix/improve debug messages for affine analysis/fusion utils (llvm#127164)
Fix/improve debug messages and API signatures for affine analysis/fusion utils. Move some warnings under LLVM_DEBUG. These weren't meant to be exposed during compilation. Add dump pretty methods for FlatLinearConstraints. NFC.
1 parent d1b95ac commit 61ad087

File tree

7 files changed

+115
-48
lines changed

7 files changed

+115
-48
lines changed

mlir/include/mlir/Analysis/FlatLinearValueConstraints.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ class FlatLinearConstraints : public presburger::IntegerPolyhedron {
194194
return appendVar(VarKind::Local, num);
195195
}
196196

197+
/// A more human-readable version of dump().
198+
void dumpPretty() const;
199+
/// An easier to read dump of a `row` of the same width as the number of
200+
/// columns. `fixedColWidth` ensure that even with a zero coefficient, we
201+
/// print spaces so that variables are aligned.
202+
void dumpRow(ArrayRef<int64_t> row, bool fixedColWidth = true) const;
203+
197204
protected:
198205
using VarKind = presburger::VarKind;
199206

mlir/include/mlir/Dialect/Affine/Analysis/Utils.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,10 @@ struct ComputationSliceState {
416416
// %v = affine.load %0[%i1] : memref<100xf32> // 'depSinkAccess'
417417
// }
418418
//
419-
void getComputationSliceState(Operation *depSourceOp, Operation *depSinkOp,
420-
FlatAffineValueConstraints *dependenceConstraints,
421-
unsigned loopDepth, bool isBackwardSlice,
422-
ComputationSliceState *sliceState);
419+
void getComputationSliceState(
420+
Operation *depSourceOp, Operation *depSinkOp,
421+
const FlatAffineValueConstraints &dependenceConstraints, unsigned loopDepth,
422+
bool isBackwardSlice, ComputationSliceState *sliceState);
423423

424424
/// Return the number of iterations for the `slicetripCountMap` provided.
425425
uint64_t getSliceIterationCount(

mlir/lib/Analysis/FlatLinearValueConstraints.cpp

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,58 @@ static bool detectAsFloorDiv(const FlatLinearConstraints &cst, unsigned pos,
445445
return true;
446446
}
447447

448+
void FlatLinearConstraints::dumpRow(ArrayRef<int64_t> row,
449+
bool fixedColWidth) const {
450+
unsigned ncols = getNumCols();
451+
bool firstNonZero = true;
452+
for (unsigned j = 0; j < ncols; j++) {
453+
if (j == ncols - 1) {
454+
// Constant.
455+
if (row[j] == 0 && !firstNonZero) {
456+
if (fixedColWidth)
457+
llvm::errs().indent(7);
458+
} else {
459+
llvm::errs() << ((row[j] >= 0) ? "+ " : "") << row[j] << ' ';
460+
}
461+
} else {
462+
std::string var = std::string("c_") + std::to_string(j);
463+
if (row[j] == 1)
464+
llvm::errs() << "+ " << var << ' ';
465+
else if (row[j] == -1)
466+
llvm::errs() << "- " << var << ' ';
467+
else if (row[j] >= 2)
468+
llvm::errs() << "+ " << row[j] << '*' << var << ' ';
469+
else if (row[j] <= -2)
470+
llvm::errs() << "- " << -row[j] << '*' << var << ' ';
471+
else if (fixedColWidth)
472+
// Zero coeff.
473+
llvm::errs().indent(7);
474+
if (row[j] != 0)
475+
firstNonZero = false;
476+
}
477+
}
478+
}
479+
480+
void FlatLinearConstraints::dumpPretty() const {
481+
assert(hasConsistentState());
482+
llvm::errs() << "Constraints (" << getNumDimVars() << " dims, "
483+
<< getNumSymbolVars() << " symbols, " << getNumLocalVars()
484+
<< " locals), (" << getNumConstraints() << " constraints)\n";
485+
auto dumpConstraint = [&](unsigned rowPos, bool isEq) {
486+
// Is it the first non-zero entry?
487+
SmallVector<int64_t> row =
488+
isEq ? getEquality64(rowPos) : getInequality64(rowPos);
489+
dumpRow(row);
490+
llvm::errs() << (isEq ? "=" : ">=") << " 0\n";
491+
};
492+
493+
for (unsigned i = 0, e = getNumInequalities(); i < e; i++)
494+
dumpConstraint(i, /*isEq=*/false);
495+
for (unsigned i = 0, e = getNumEqualities(); i < e; i++)
496+
dumpConstraint(i, /*isEq=*/true);
497+
llvm::errs() << '\n';
498+
}
499+
448500
std::pair<AffineMap, AffineMap> FlatLinearConstraints::getLowerAndUpperBound(
449501
unsigned pos, unsigned offset, unsigned num, unsigned symStartPos,
450502
ArrayRef<AffineExpr> localExprs, MLIRContext *context,
@@ -544,9 +596,9 @@ void FlatLinearConstraints::getSliceBounds(unsigned offset, unsigned num,
544596
// Basic simplification.
545597
normalizeConstraintsByGCD();
546598

547-
LLVM_DEBUG(llvm::dbgs() << "getSliceBounds for first " << num
548-
<< " variables\n");
549-
LLVM_DEBUG(dump());
599+
LLVM_DEBUG(llvm::dbgs() << "getSliceBounds for variables at positions ["
600+
<< offset << ", " << offset + num << ")\n");
601+
LLVM_DEBUG(dumpPretty());
550602

551603
// Record computed/detected variables.
552604
SmallVector<AffineExpr, 8> memo(getNumVars());
@@ -699,12 +751,12 @@ void FlatLinearConstraints::getSliceBounds(unsigned offset, unsigned num,
699751
}
700752
}
701753
}
702-
LLVM_DEBUG(llvm::dbgs()
703-
<< "lb map for pos = " << Twine(pos + offset) << ", expr: ");
704-
LLVM_DEBUG(lbMap.dump(););
705-
LLVM_DEBUG(llvm::dbgs()
706-
<< "ub map for pos = " << Twine(pos + offset) << ", expr: ");
707-
LLVM_DEBUG(ubMap.dump(););
754+
755+
LLVM_DEBUG(llvm::dbgs() << "Slice bounds:\n");
756+
LLVM_DEBUG(llvm::dbgs() << "lb map for pos = " << Twine(pos + offset)
757+
<< ", expr: " << lbMap << '\n');
758+
LLVM_DEBUG(llvm::dbgs() << "ub map for pos = " << Twine(pos + offset)
759+
<< ", expr: " << ubMap << '\n');
708760
}
709761
}
710762

mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,9 @@ template bool mlir::affine::isInvariantAccess(AffineStoreOp, AffineForOp);
182182
DenseSet<Value> mlir::affine::getInvariantAccesses(Value iv,
183183
ArrayRef<Value> indices) {
184184
DenseSet<Value> res;
185-
for (auto val : indices) {
186-
if (isAccessIndexInvariant(iv, val)) {
187-
res.insert(val);
188-
}
185+
for (Value index : indices) {
186+
if (isAccessIndexInvariant(iv, index))
187+
res.insert(index);
189188
}
190189
return res;
191190
}

mlir/lib/Dialect/Affine/Analysis/Utils.cpp

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ bool MemRefDependenceGraph::init() {
249249
// the memref.
250250
DenseMap<Value, SetVector<unsigned>> memrefAccesses;
251251

252+
// Create graph nodes.
252253
DenseMap<Operation *, unsigned> forToNodeMap;
253254
for (Operation &op : block) {
254255
if (auto forOp = dyn_cast<AffineForOp>(op)) {
@@ -300,11 +301,7 @@ bool MemRefDependenceGraph::init() {
300301
// interface.
301302
}
302303

303-
for (auto &idAndNode : nodes) {
304-
LLVM_DEBUG(llvm::dbgs() << "Create node " << idAndNode.first << " for:\n"
305-
<< *(idAndNode.second.op) << "\n");
306-
(void)idAndNode;
307-
}
304+
LLVM_DEBUG(llvm::dbgs() << "Created " << nodes.size() << " nodes\n");
308305

309306
// Add dependence edges between nodes which produce SSA values and their
310307
// users. Load ops can be considered as the ones producing SSA values.
@@ -1556,9 +1553,9 @@ mlir::affine::computeSliceUnion(ArrayRef<Operation *> opsA,
15561553
FlatAffineValueConstraints sliceUnionCst;
15571554
assert(sliceUnionCst.getNumDimAndSymbolVars() == 0);
15581555
std::vector<std::pair<Operation *, Operation *>> dependentOpPairs;
1559-
for (auto *i : opsA) {
1556+
for (Operation *i : opsA) {
15601557
MemRefAccess srcAccess(i);
1561-
for (auto *j : opsB) {
1558+
for (Operation *j : opsB) {
15621559
MemRefAccess dstAccess(j);
15631560
if (srcAccess.memref != dstAccess.memref)
15641561
continue;
@@ -1587,7 +1584,7 @@ mlir::affine::computeSliceUnion(ArrayRef<Operation *> opsA,
15871584

15881585
// Compute slice bounds for 'srcAccess' and 'dstAccess'.
15891586
ComputationSliceState tmpSliceState;
1590-
mlir::affine::getComputationSliceState(i, j, &dependenceConstraints,
1587+
mlir::affine::getComputationSliceState(i, j, dependenceConstraints,
15911588
loopDepth, isBackwardSlice,
15921589
&tmpSliceState);
15931590

@@ -1646,8 +1643,10 @@ mlir::affine::computeSliceUnion(ArrayRef<Operation *> opsA,
16461643
}
16471644

16481645
// Empty union.
1649-
if (sliceUnionCst.getNumDimAndSymbolVars() == 0)
1646+
if (sliceUnionCst.getNumDimAndSymbolVars() == 0) {
1647+
LLVM_DEBUG(llvm::dbgs() << "empty slice union - unexpected\n");
16501648
return SliceComputationResult::GenericFailure;
1649+
}
16511650

16521651
// Gather loops surrounding ops from loop nest where slice will be inserted.
16531652
SmallVector<Operation *, 4> ops;
@@ -1686,7 +1685,8 @@ mlir::affine::computeSliceUnion(ArrayRef<Operation *> opsA,
16861685
sliceUnion->ivs.clear();
16871686
sliceUnionCst.getValues(0, numSliceLoopIVs, &sliceUnion->ivs);
16881687

1689-
// Set loop nest insertion point to block start at 'loopDepth'.
1688+
// Set loop nest insertion point to block start at 'loopDepth' for forward
1689+
// slices, while at the end for backward slices.
16901690
sliceUnion->insertPoint =
16911691
isBackwardSlice
16921692
? surroundingLoops[loopDepth - 1].getBody()->begin()
@@ -1785,7 +1785,7 @@ const char *const kSliceFusionBarrierAttrName = "slice_fusion_barrier";
17851785
// the other loop nest's IVs, symbols and constants (using 'isBackwardsSlice').
17861786
void mlir::affine::getComputationSliceState(
17871787
Operation *depSourceOp, Operation *depSinkOp,
1788-
FlatAffineValueConstraints *dependenceConstraints, unsigned loopDepth,
1788+
const FlatAffineValueConstraints &dependenceConstraints, unsigned loopDepth,
17891789
bool isBackwardSlice, ComputationSliceState *sliceState) {
17901790
// Get loop nest surrounding src operation.
17911791
SmallVector<AffineForOp, 4> srcLoopIVs;
@@ -1804,30 +1804,28 @@ void mlir::affine::getComputationSliceState(
18041804
unsigned pos = isBackwardSlice ? numSrcLoopIVs + loopDepth : loopDepth;
18051805
unsigned num =
18061806
isBackwardSlice ? numDstLoopIVs - loopDepth : numSrcLoopIVs - loopDepth;
1807-
dependenceConstraints->projectOut(pos, num);
1807+
FlatAffineValueConstraints sliceCst(dependenceConstraints);
1808+
sliceCst.projectOut(pos, num);
18081809

18091810
// Add slice loop IV values to 'sliceState'.
18101811
unsigned offset = isBackwardSlice ? 0 : loopDepth;
18111812
unsigned numSliceLoopIVs = isBackwardSlice ? numSrcLoopIVs : numDstLoopIVs;
1812-
dependenceConstraints->getValues(offset, offset + numSliceLoopIVs,
1813-
&sliceState->ivs);
1813+
sliceCst.getValues(offset, offset + numSliceLoopIVs, &sliceState->ivs);
18141814

18151815
// Set up lower/upper bound affine maps for the slice.
18161816
sliceState->lbs.resize(numSliceLoopIVs, AffineMap());
18171817
sliceState->ubs.resize(numSliceLoopIVs, AffineMap());
18181818

18191819
// Get bounds for slice IVs in terms of other IVs, symbols, and constants.
1820-
dependenceConstraints->getSliceBounds(offset, numSliceLoopIVs,
1821-
depSourceOp->getContext(),
1822-
&sliceState->lbs, &sliceState->ubs);
1820+
sliceCst.getSliceBounds(offset, numSliceLoopIVs, depSourceOp->getContext(),
1821+
&sliceState->lbs, &sliceState->ubs);
18231822

18241823
// Set up bound operands for the slice's lower and upper bounds.
18251824
SmallVector<Value, 4> sliceBoundOperands;
1826-
unsigned numDimsAndSymbols = dependenceConstraints->getNumDimAndSymbolVars();
1825+
unsigned numDimsAndSymbols = sliceCst.getNumDimAndSymbolVars();
18271826
for (unsigned i = 0; i < numDimsAndSymbols; ++i) {
1828-
if (i < offset || i >= offset + numSliceLoopIVs) {
1829-
sliceBoundOperands.push_back(dependenceConstraints->getValue(i));
1830-
}
1827+
if (i < offset || i >= offset + numSliceLoopIVs)
1828+
sliceBoundOperands.push_back(sliceCst.getValue(i));
18311829
}
18321830

18331831
// Give each bound its own copy of 'sliceBoundOperands' for subsequent
@@ -2055,16 +2053,18 @@ static std::optional<int64_t> getMemoryFootprintBytes(Block &block,
20552053
if (failed(
20562054
region->compute(opInst,
20572055
/*loopDepth=*/getNestingDepth(&*block.begin())))) {
2058-
return opInst->emitError("error obtaining memory region\n");
2056+
LLVM_DEBUG(opInst->emitError("error obtaining memory region"));
2057+
return failure();
20592058
}
20602059

20612060
auto [it, inserted] = regions.try_emplace(region->memref);
20622061
if (inserted) {
20632062
it->second = std::move(region);
20642063
} else if (failed(it->second->unionBoundingBox(*region))) {
2065-
return opInst->emitWarning(
2064+
LLVM_DEBUG(opInst->emitWarning(
20662065
"getMemoryFootprintBytes: unable to perform a union on a memory "
2067-
"region");
2066+
"region"));
2067+
return failure();
20682068
}
20692069
return WalkResult::advance();
20702070
});

mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,15 @@ struct GreedyFusion {
836836
// Get 'srcNode' from which to attempt fusion into 'dstNode'.
837837
auto *srcNode = mdg->getNode(srcId);
838838
auto srcAffineForOp = cast<AffineForOp>(srcNode->op);
839+
840+
LLVM_DEBUG(llvm::dbgs()
841+
<< "Trying to fuse producer loop nest " << srcId
842+
<< " with consumer loop nest " << dstId << "\n");
843+
LLVM_DEBUG(llvm::dbgs()
844+
<< "Producer loop nest:\n"
845+
<< *srcNode->op << "\n and consumer loop nest:\n"
846+
<< *dstNode->op << '\n');
847+
839848
LLVM_DEBUG(llvm::dbgs() << "Evaluating src loop " << srcId
840849
<< " for dst loop " << dstId << "\n");
841850

@@ -904,9 +913,11 @@ struct GreedyFusion {
904913
affine::canFuseLoops(srcAffineForOp, dstAffineForOp,
905914
/*dstLoopDepth=*/i + numSurroundingLoops,
906915
&depthSliceUnions[i - 1], strategy);
907-
908-
if (result.value == FusionResult::Success)
916+
if (result.value == FusionResult::Success) {
909917
maxLegalFusionDepth = i;
918+
LLVM_DEBUG(llvm::dbgs()
919+
<< "Found valid slice for depth: " << i << '\n');
920+
}
910921
}
911922

912923
if (maxLegalFusionDepth == 0) {

mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "llvm/Support/raw_ostream.h"
2626
#include <optional>
2727

28-
#define DEBUG_TYPE "loop-fusion-utils"
28+
#define DEBUG_TYPE "affine-fusion-utils"
2929

3030
using namespace mlir;
3131
using namespace mlir::affine;
@@ -49,12 +49,10 @@ static void getLoadAndStoreMemRefAccesses(Operation *opA,
4949
/// Returns false otherwise.
5050
static bool isDependentLoadOrStoreOp(Operation *op,
5151
DenseMap<Value, bool> &values) {
52-
if (auto loadOp = dyn_cast<AffineReadOpInterface>(op)) {
52+
if (auto loadOp = dyn_cast<AffineReadOpInterface>(op))
5353
return values.count(loadOp.getMemRef()) > 0 && values[loadOp.getMemRef()];
54-
}
55-
if (auto storeOp = dyn_cast<AffineWriteOpInterface>(op)) {
54+
if (auto storeOp = dyn_cast<AffineWriteOpInterface>(op))
5655
return values.count(storeOp.getMemRef()) > 0;
57-
}
5856
return false;
5957
}
6058

0 commit comments

Comments
 (0)