Background
MLIR has a strong sense of generality, as its ops can represent the computational process of a complete program or an instruction. However, the current description of memory side effects in MLIR only covers the affected values, which is far from sufficient.
Motivation example
If we are trying to implement copy propagation pass on mlir.
Consirder the following input ir:
...
memref.copy %a, %b ...
xx.compute %b, %b // Read from %b and write to %b.
...
We cannot infer whether copy propagation can be performed from the intermediate representation above because we donāt know the order of operations in xx.compute
- whether the read or write occurs first. If the read happens before the write, then we can eliminate the copy and replace the read operand of xx.compute
with %a
. However, if the write happens before the read, this substitution would be illegal.
Proposal
We plan to add an index to describe the order of memory side effects. This index will indicate the sequence in which the side effects occur. To ensure backward compatibility with existing code, we will set the default index for all memory side effects to 0. Users will have the option to specify the order of memory side effects either by calling the builder in a specific way or by using a different writing style in the td file.
Changes to the EffectInstance builder:
EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get(), unsigned index = 0)
: effect(effect), resource(resource), index(index) {}
Changes to the td files:
def CopyOp : MemRef_Op<"copy", [CopyOpInterface, SameOperandsElementType,
SameOperandsShape]> {
let description = [{
Copies the data from the source to the destination memref.
Usage:
```mlir
memref.copy %arg0, %arg1 : memref<?xf32> to memref<?xf32>
```
Source and destination are expected to have the same element type and shape.
Otherwise, the result is undefined. They may have different layouts.
}];
let arguments = (ins Arg<AnyRankedOrUnrankedMemRef, "the memref to copy from",
[MemReadAt<"0">]>:$source,
Arg<AnyRankedOrUnrankedMemRef, "the memref to copy to",
[MemWriteAt<"1">]>:$target);
let assemblyFormat = [{
$source `,` $target attr-dict `:` type($source) `to` type($target)
}];
let hasCanonicalizer = 1;
let hasFolder = 1;
}
Compatibility
All previous builder and td writing styles will remain compatible.
Commit
https://reviews.llvm.org/D156087
Thank you for any suggestionć