This is to inform that the code generation for tablegen passes has been recently improved. The docs have already been updated (again, feel free to improve them), but here I provide a short summary of the changes for better transitioning.
- Individual guards are now being emitted for the passes, and are furthermore differentiated between declarations and definitions (which are respectively guarded by the
GEN_PASS_DECL_PASSNAME
andGEN_PASS_DEF_PASSNAME
macros). - All of the code is still generated inside the
.h.inc
file, but the pass base classes now live inside theimpl
namespace. - If the pass has some options, an options struct is also declared and can be passed to the pass base class constructor to set the options of the pass itself.
- The
constructor
field has also become optional within the tablegen declaration and, if not provided, the infrastructure will generate both the C++ declarations and definitions, using a function name that is derived from the pass name.
Notice that the constructor would still need to be explicitely declared in these cases, even if the name of the function would match the autogenerated one:- if living in a namespace that is different from the registration code.
- if having a return type different from
std::unique_ptr<mlir::Pass>
This is an example of how the code should look like when migrating to the new infrastructure:
/** PassName.h */
namespace mlir {
#define GEN_PASS_DECL_PASSNAME
#include "Passes.h.inc"
// If constructor is explicit
std::unique_ptr<mlir::Pass> createPassName(); // Explicit constructor is needed if mlir::Pass has to be replaced with, for example, mlir::OperationPass<>
// If constructor is explicit and pass has options
std::unique_ptr<mlir::Pass> createPassName(const PassNameOptions &options); // Explicit constructor is needed if mlir::Pass has to be replaced with, for example, mlir::OperationPass<>
}
/** Passes.h */
#include "PassName.h"
namespace mlir {
#define GEN_PASS_REGISTRATION
#include "Passes.h.inc"
}
/** PassName.cpp */
namespace mlir {
#define GEN_PASS_DEF_PASSNAME
#include "Passes.h.inc"
}
namespace {
// Name of the class must match the tablegen name if the constructor is autogenerated
struct PassName : public mlir::impl::PassNameBase {
using PassNameBase::PassNameBase;
...
}
}
// If the constructor is explicit
std::unique_ptr<mlir::Pass> mlir::createPassName() {
return std::make_unique<PassName>();
}
// If constructor is explicit and pass has options
std::unique_ptr<mlir::Pass> mlir::createPassName(const mlir::PassNameOptions& options) {
return std::make_unique<PassName>(options);
}
For what regards the MLIR core, a GitHub issue has been opened to improve the passes to the new best practices. Any help is welcome, there are also some “design” topics to be discussed among the lines.
The generation of the old pass base classes (guarded by the GEN_PASS_CLASSES
macro) has been kept in order to ease the migration of downstream code, but we plan to drop it in something like 6 weeks from now. That should be a sufficient time window to perform the required changes.