This pass performs various types of canonicalizations over a set of 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.
This interface is used in conjunction with transform_spills so that the transform can be used
with any dialect, and more importantly, avoids forming a dependency on our own dialects for the
subset of operations we need to emit/rewrite.
This transformation rewrites op by applying the results of the provided SpillAnalysis,
using the provided implementation of the TransformSpillsInterface.