This is an archive of the discontinued LLVM Phabricator instance.

[mlir] Affine symbols: do not expect AffineScope to always exist
ClosedPublic

Authored by ftynse on Jun 12 2020, 11:47 AM.

Details

Summary

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.

Diff Detail

Event Timeline

ftynse created this revision.Jun 12 2020, 11:47 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 12 2020, 11:47 AM

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?

andydavis1 accepted this revision.Jun 12 2020, 12:19 PM
This revision is now accepted and ready to land.Jun 12 2020, 12:19 PM

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.

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).

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.

This revision was automatically updated to reflect the committed changes.