While debugging this error, I met another problem while trying to print intermediate lowering from Linalg to LLVM.
I am trying to optimize a single Linalg.Matmul operator.
This is the sequence of passes I am using:
// Run the passes and print the intermediate MLIR module
Now, I would like to print the intermediate IR after createLinalgCodegenPass, which is a pass I created (following mmperf) that basically tiles/promotes/vectorizes the operation.
However, when I run the pass manager after createLinalgCodegenPass (as shown in the snippet) I get this error: LLVM ERROR: Building op `vector.transfer_read` but it isn't registered in this MLIRContext
I have registered the Vector dialect and I am also allowing unregistered ops. If I run the passes after the createLowerAffinePass, everything works, but I am not able to see the intermediate IR. Why is it raising this error?
This error usually means that the pass does not declare the relevant dialect (vector in this case) as dependent. See FAQ - MLIR. Registering a dialect with the context does not automatically make its operations registered. (The terminology is confusing here).
Thank you so much for your help, it works now. Can I ask more about the difference between Loading a dialect and declaring it as dependent from a pass?
I was indeed loading all dialects in the context, but I was not inserting the VectorDialect in the registry during getDependentDialects. Why is this necessary? The FAQ says:
The process of loading a Dialect in the context is not thread-safe, which forces all involved Dialects to be loaded before the multi-threaded pass manager starts the execution. To keep the system modular and layered, invoking a pass pipeline should never require pre-loading dialects explicitly. This is achieved by requiring every pass to declare a list of dependent Dialects: these are Dialects for which an entity (Operation, Type, or Attribute) can be created by the pass, other than for Dialects that would already be in the input.
Does it mean that when I load a dialect into the context I am not loading its operations? So those operations only get loaded from within the pass?
This is rather peculiar. Listing a dialect as dependent in a pass makes pass manager load this dialect before it runs the pipeline. If the dialect is already loaded (being registered is not sufficient), this should not be necessary. There may be something going on with multiple contexts, linkage-level registration or ordering (e.g., the vector dialect is not registered with the context when loadAllAvaiableDialects is called).
Coincidentally, we just ran into a similar-looking issue in Cuda backend build failure · Issue #6979 · google/iree · GitHub. I’m glad this thread was just here because I also assumed it was an issue with not having registered the GPU dialect, which I was pretty sure we’d registered. Could we add a hint to that error message like “Has its dialect been loaded?” to indicate the problem is likely from having failed to load the necessary dialect?
context.loadAllAvailableDialects() will load all the dialects that are registered with the context, while registry.loadAll(&context); will load the dialects registered in this particular registry with the provided context. Other dialects previously registered with the context, but not in this particular registry won’t be loaded.
In general for a “production” system (I’d say anything that is more than quick prototyping) should never have to explicitly load any dialect (other than the one emitted programmatically by a frontend).
(Similarly, I avoid allowUnregisteredDialects as much as possible beyond prototyping).
That’s a good idea!
I’m slightly nervous about the lack of stability of URLs (It may be why Microsoft and others are using error codes instead, it is easier to manage the redirection as well).