blob: 8c4f64de477959c0f473d6e3b58952fa35bec9c9 [file]
//===- TestTilingInterfaceTransformOps.td -----------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef TEST_TILINGINTERFACE_TRANSFORM_OPS
#define TEST_TILINGINTERFACE_TRANSFORM_OPS
include "mlir/Dialect/SCF/IR/DeviceMappingInterface.td"
include "mlir/Dialect/Transform/IR/TransformDialect.td"
include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td"
include "mlir/Dialect/Transform/IR/TransformTypes.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/IR/OpBase.td"
// Those operations in this file are meant for testing the tiling interface
// transformations using scf operations. Over time these testing options
// might be useful transformations in their own right. Move these over
// as transform ops in the main repo (also find a proper place for them)
def TestFuseAndYieldOp : Op<Transform_Dialect, "test.fuse_and_yield",
[FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface,
DeclareOpInterfaceMethods<TransformOpInterface>,
ReportTrackingListenerFailuresOpTrait]> {
let description = [{
Tiles the operations pointed to by the target handle, fuses their
producers greedily using the options provided as attributes.
It also yields some of the fused producers for testing.
On success returns the tiled operations as well as generated loops. Emits
a definite failure if tiling fails.
}];
let arguments =
(ins TransformHandleTypeInterface:$target,
DefaultValuedAttr<I64ArrayAttr, "{}">:$tile_sizes,
DefaultValuedAttr<I64ArrayAttr, "{}">:$tile_interchange,
DefaultValuedAttr<BoolAttr, "false">:$use_forall);
let results = (outs TransformHandleTypeInterface:$transfomed,
Variadic<TransformHandleTypeInterface>:$loops);
let assemblyFormat = [{
$target ($tile_sizes^)? (`interchange` $tile_interchange^)?
(`use_forall` $use_forall^)? attr-dict
`:` functional-type(operands, results)
}];
}
def TestFuseConsumerUsingSliceOp : Op<Transform_Dialect, "test.fuse_consumer_using_slice",
[AttrSizedOperandSegments,
DeclareOpInterfaceMethods<TransformOpInterface>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
ReportTrackingListenerFailuresOpTrait]> {
let description = [{
For the `insert_slice`-like operations (that are typically generated through tiling),
within the loop nests passed in as `loops` (that are typically generated through tiling),
find the consumer that these slices map to (have to be the same consumer) and fuse
the consumer into the loop.
Returns a handle to the original consumer operation and the consumer operation after
fusion.
}];
let arguments = (ins
Variadic<TransformHandleTypeInterface>:$targets,
Variadic<TransformHandleTypeInterface>:$loops,
DefaultValuedAttr<I32Attr, "1">:$num_consumer_to_fuse);
let results = (outs TransformHandleTypeInterface:$consumer,
TransformHandleTypeInterface:$fused_consumer);
let assemblyFormat = [{
$targets `in` `(` $loops `)`
(`num_consumer_to_fuse` `=` $num_consumer_to_fuse^)?
attr-dict `:` functional-type(operands, results)
}];
}
def TestFuseConsumerOp : Op<Transform_Dialect, "test.fuse_consumer",
[DeclareOpInterfaceMethods<TransformOpInterface>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
ReportTrackingListenerFailuresOpTrait]> {
let description = [{
For the `consumer` that uses the result of the outer-most loop of a loop nest passed in
as `loops` (that are typically generated through tiling), fuse the consumer into the
loop.
Returns a handle to the consumer operation after fusion and the loops that might be
modified.
}];
let arguments = (ins
TransformHandleTypeInterface:$consumer,
Variadic<TransformHandleTypeInterface>:$loops);
let results = (outs TransformHandleTypeInterface:$fused_consumer,
Variadic<TransformHandleTypeInterface>:$result_loops);
let assemblyFormat = [{
$consumer `into` `(` $loops `)`
attr-dict `:` functional-type(operands, results)
}];
}
def TestTileUsingForallOp : Op<Transform_Dialect, "test.tile_using_forall",
[DeclareOpInterfaceMethods<TransformOpInterface>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
ReportTrackingListenerFailuresOpTrait]> {
let description = [{
Test operation use to test tiling using TilingInterface and scf.forall for
the loop constructs. This is similar to
`transform.structured.tile_using_for`. Use of this operation is an
intermediate state and will be replaced in due course with either
`transform.structured.tile_using_for` or
`transform.structured.tile_using_forall`.
On success returns the tiled operations as well as generated loops. Emits
a definite failure if tiling fails.
}];
let arguments = (ins TransformHandleTypeInterface:$target,
DefaultValuedAttr<I64ArrayAttr, "{}">:$tile_sizes,
DefaultValuedOptionalAttr<I64ArrayAttr, "{}">:$interchange,
OptionalAttr<DeviceMappingArrayAttr>:$mapping);
let results = (outs TransformHandleTypeInterface:$tiled_op,
Variadic<TransformHandleTypeInterface>:$loops);
let assemblyFormat = [{
$target ($tile_sizes^)? (`interchange` `=` $interchange^)?
(`mapping` `=` $mapping^)?
attr-dict `:` functional-type(operands, results)
}];
}
def TestFuseUsingForallOp : Op<Transform_Dialect, "test.fuse_using_forall",
[DeclareOpInterfaceMethods<TransformOpInterface>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
ReportTrackingListenerFailuresOpTrait]> {
let description = [{
Test operation to tile the operation pointed to by the target handle and
fuses their producers greedily using the options provided as attributes.
This operation uses scf.forall for the loop construct.
}];
let arguments = (ins TransformHandleTypeInterface:$root_op,
DefaultValuedAttr<I64ArrayAttr, "{}">:$tile_sizes,
DefaultValuedOptionalAttr<I64ArrayAttr, "{}">:$interchange,
OptionalAttr<DeviceMappingArrayAttr>:$mapping);
let results = (outs TransformHandleTypeInterface:$tiled_ops,
Variadic<TransformHandleTypeInterface>:$loops);
let assemblyFormat = [{
$root_op ($tile_sizes^)? (`interchange` $interchange^)?
(`mapping` `=` $mapping^)?
attr-dict `:` functional-type(operands, results)
}];
}
def TestTileAndFuseOuterParallelPartialReductionOp : Op<
Transform_Dialect, "test.tile_and_fuse_outer_parallel_partial_reduction",
[FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface,
DeclareOpInterfaceMethods<TransformOpInterface>,
ReportTrackingListenerFailuresOpTrait]> {
let description = [{
Test operation to tile an operation using partial reduction with
outer parallel strategy, and to fuse its producers.
}];
let arguments = (ins TransformHandleTypeInterface:$root_op,
DefaultValuedAttr<I64ArrayAttr, "{}">:$reduction_dims,
DefaultValuedAttr<I64ArrayAttr, "{}">:$tile_sizes,
OptionalAttr<DeviceMappingArrayAttr>:$mapping);
let results = (outs TransformHandleTypeInterface:$tiled_ops,
Variadic<TransformHandleTypeInterface>:$loops);
let assemblyFormat = [{
$root_op (`reduction_dims` `=` $reduction_dims^)?
(`tile_sizes` `=` $tile_sizes^)? (`mapping` `=` $mapping^)?
attr-dict `:` functional-type(operands, results)
}];
}
def TestTileUsingCustomLoopOp : Op<
Transform_Dialect, "test.tile_using_custom_loop",
[FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface,
DeclareOpInterfaceMethods<TransformOpInterface>,
ReportTrackingListenerFailuresOpTrait]> {
let description = [{
Test Transform op to tile an operation using custom loops.
The test just folds all the loops and into a single loop and then
delinearizes the indices.
}];
let arguments = (ins TransformHandleTypeInterface:$root_op,
DefaultValuedAttr<I64ArrayAttr, "{}">:$tile_sizes);
let results = (outs TransformHandleTypeInterface:$tiled_ops,
Variadic<TransformHandleTypeInterface>:$loops);
let assemblyFormat = [{
$root_op `tile_sizes` `=` $tile_sizes
attr-dict `:` functional-type(operands, results)
}];
}
def TestQueryProducerFusability : Op<
Transform_Dialect, "test.query_producer_fusability",
[DeclareOpInterfaceMethods<TransformOpInterface>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
let description = [{
Test operation for the producer fusability query method in the
TilingInterface.
For each operation in the target handle, this looks for tensor.insert_slice
ops that produce operands to the tilable op. The offset/sizes from those
inserts is used as the arguments to `isOpFusableWithProducerSlices` and
emits a remark with the result of the query.
}];
let arguments = (ins TransformHandleTypeInterface:$target);
let results = (outs);
let assemblyFormat = [{
$target attr-dict `:` type($target)
}];
}
def TestQueryConsumerFusability
: Op<Transform_Dialect, "test.query_consumer_fusability",
[DeclareOpInterfaceMethods<TransformOpInterface>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
let description = [{
Test operation for the consumer fusability query method in the
TilingInterface.
For each operation in the target handle, this looks for tensor.extract_slice
ops that consume results of the tilable op. The offset/sizes from those
extracts is used as the arguments to `isOpFusableWithConsumerSlice` and
emits a remark with the result of the query.
}];
let arguments = (ins TransformHandleTypeInterface:$target);
let results = (outs);
let assemblyFormat = [{
$target attr-dict `:` type($target)
}];
}
#endif // TEST_TILINGINTERFACE_TRANSFORM_OPS