[mlir][transforms][NFC] Expand CanonicalizerPass documentation

Mention that canonicalization is best-effort and that pass pipelines should not rely on it for correctness.

RFC: https://discourse.llvm.org/t/rfc-canonicalizerpass-convergence-error-handling/67333

Differential Revision: https://reviews.llvm.org/D140729
This commit is contained in:
Matthias Springer
2023-01-03 11:48:38 +01:00
parent f492db7eec
commit afc800b190
3 changed files with 24 additions and 6 deletions

View File

@@ -19,15 +19,28 @@ to capture IR-specific rules for reference.
## General Design
MLIR has a single canonicalization pass, which iteratively applies
canonicalization transformations in a greedy way until the IR converges. These
transformations are defined by the operations themselves, which allows each
dialect to define its own set of operations and canonicalizations together.
MLIR has a single canonicalization pass, which iteratively applies the
canonicalization patterns of all loaded dialects in a greedy way.
Canonicalization is best-effort and not guaranteed to bring the entire IR in a
canonical form. It applies patterns until either fixpoint is reached or the
maximum number of iterations/rewrites (as specified via pass options) is
exhausted. This is for efficiency reasons and to ensure that faulty patterns
cannot cause infinite looping.
Canonicalization patterns are registered with the operations themselves, which
allows each dialect to define its own set of operations and canonicalizations
together.
Some important things to think about w.r.t. canonicalization patterns:
* Pass pipelines should not rely on the canonicalizer pass for correctness.
They should work correctly with all instances of the canonicalization pass
removed.
* Repeated applications of patterns should converge. Unstable or cyclic
rewrites will cause infinite loops in the canonicalizer.
rewrites are considered a bug: they can make the canonicalizer pass less
predictable and less effective (i.e., some patterns may not be applied) and
prevent it from converging.
* It is generally better to canonicalize towards operations that have fewer
uses of a value when the operands are duplicated, because some patterns only

View File

@@ -20,7 +20,11 @@ def Canonicalizer : Pass<"canonicalize"> {
let summary = "Canonicalize operations";
let description = [{
This pass performs various types of canonicalizations over a set of
operations. See [Operation Canonicalization](Canonicalization.md) for more
operations by iteratively applying the canonicalization patterns of all
loaded dialects until either a fixpoint is reached or the maximum number of
iterations/rewrites is exhausted. Canonicalization is best-effort and does
not guarantee that the entire IR is in a canonical form after running this
pass. See [Operation Canonicalization](Canonicalization.md) for more
details.
}];
let constructor = "mlir::createCanonicalizerPass()";

View File

@@ -57,6 +57,7 @@ struct Canonicalizer : public impl::CanonicalizerBase<Canonicalizer> {
config.enableRegionSimplification = enableRegionSimplification;
config.maxIterations = maxIterations;
config.maxNumRewrites = maxNumRewrites;
// Canonicalization is best-effort. Non-convergence is not a pass failure.
(void)applyPatternsAndFoldGreedily(getOperation(), patterns, config);
}