This patch takes the first step towards a more principled modeling of undefined behavior in MLIR as discussed in the following discourse threads:
- https://discourse.llvm.org/t/semantics-modeling-undefined-behavior-and-side-effects/4812
- https://discourse.llvm.org/t/rfc-mark-tensor-dim-and-memref-dim-as-side-effecting/65729
This patch in particular does the following:
- Introduces a ConditionallySpeculatable OpInterface that dynamically determines whether an Operation can be speculated.
- Re-defines NoSideEffect to allow undefined behavior, making it necessary but not sufficient for speculation. Also renames it to NoMemoryEffect.
- Makes LICM respect the above semantics.
- Changes all ops tagged with NoSideEffect today to additionally implement ConditionallySpeculatable and mark themselves as always speculatable. This combined trait is named Pure. This makes this change NFC.
For out of tree dialects:
- Replace NoSideEffect with Pure if the operation does not have any memory effects, undefined behavior or infinite loops.
- Replace NoSideEffect with NoSideEffect otherwise.
The next steps in this process are (I'm proposing to do these in upcoming patches):
- Update operations like tensor.dim, memref.dim, scf.for, affine.for to implement a correct hook for ConditionallySpeculatable. I'm also happy to update ops in other dialects if the respective dialect owners would like to and can give me some pointers.
- Update other passes that speculate operations to consult ConditionallySpeculatable in addition to NoMemoryEffect. I could not find any other than LICM on a quick skim, but I could have missed some.
- Add some documentation / FAQs detailing the differences between side effects, undefined behavior, speculatabilty.
Is this really useful to add here? I'd rather just remove this and actually add it in the future if necessary.