In the affine symbol and dimension check, the code currently assumes
getAffineScope and its users isValidDim and isValidSymbol are only called
on values defined in regions that have a parent Op with AffineScope trait.
This is not necessarily the case, and these functions may be called on valid IR
that does not satisfy this assumption. Return nullptr from getAffineScope
if there is no parent op with AffineScope trait. Treat this case
conservatively in isValidSymbol by only accepting as symbols the values that
are guaranteed to be symbols (constants, and certain operations). No
modifications are necessary to isValidDim that delegates most of the work to
isValidDim.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
There was an assumption that valid IR would always live inside a ModuleOp, which has the AffineScope trait. This isn't true any more? Are you referring to unlinked blocks as valid IR?
We don't enforce a top-level module at the moment (you can construct such IR and it'll pass the verifier).
There is such an example in-tree with the SPIRVDeserializer which produces a SPIRVModuleOp that isn't wrapped in a ModuleOp.
Verifier is a bit overloaded, because it isn't clear what you mean. The only reason we have a "top-level" verify method is because dominance was previously out of IR/. Given that you can't run passes without a Module, and many other parts of the infra explicitly assume a top-level module. I'd say it is a relatively fair assumption to make.
There is such an example in-tree with the SPIRVDeserializer which produces a SPIRVModuleOp that isn't wrapped in a ModuleOp.
Realistically, that could just a take a builder instead of returning a SPIRVModuleOp.
I've hit both cases:
- upstream, we call into these functions when building IR in a detached region;
- in an out-of-tree project, we have a custom top-level op.
The change makes both cases work conservatively and doesn't break anything upstream.