1,342 changes: 699 additions & 643 deletions mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions mlir/include/mlir/Dialect/SCF/Transforms/Transforms.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ void naivelyFuseParallelOps(Region &region);
/// }
/// ```
///
/// After loop peeling, this function tries to simplify/canonicalize affine.min
/// and affine.max ops in the body of the peeled loop and in the body of the
/// partial iteration loop, taking advantage of the fact that the peeled loop
/// has only "full" iterations. This canonicalization is expected to enable
/// further canonicalization opportunities through other patterns.
/// After loop peeling, this function tries to simplify affine.min and
/// affine.max ops in the body of the peeled loop and in the body of the partial
/// iteration loop, taking advantage of the fact that the peeled loop has only
/// "full" iterations. This simplification is expected to enable further
/// canonicalization opportunities through other patterns.
///
/// The return value indicates whether the loop was rewritten or not. Loops are
/// not rewritten if:
Expand All @@ -85,8 +85,8 @@ void naivelyFuseParallelOps(Region &region);
/// Note: This function rewrites the given scf.for loop in-place and creates a
/// new scf.for operation for the last iteration. It replaces all uses of the
/// unpeeled loop with the results of the newly generated scf.for.
LogicalResult peelAndCanonicalizeForLoop(RewriterBase &rewriter, ForOp forOp,
scf::ForOp &partialIteration);
LogicalResult peelForLoopAndSimplifyBounds(RewriterBase &rewriter, ForOp forOp,
scf::ForOp &partialIteration);

/// Tile a parallel loop of the form
/// scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3)
Expand Down
35 changes: 20 additions & 15 deletions mlir/lib/Analysis/SliceAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ static void getForwardSliceImpl(Operation *op,
}

void mlir::getForwardSlice(Operation *op, SetVector<Operation *> *forwardSlice,
TransitiveFilter filter) {
TransitiveFilter filter, bool inclusive) {
getForwardSliceImpl(op, forwardSlice, filter);
// Don't insert the top level operation, we just queried on it and don't
// want it in the results.
forwardSlice->remove(op);
if (!inclusive) {
// Don't insert the top level operation, we just queried on it and don't
// want it in the results.
forwardSlice->remove(op);
}

// Reverse to get back the actual topological order.
// std::reverse does not work out of the box on SetVector and I want an
Expand All @@ -65,7 +67,7 @@ void mlir::getForwardSlice(Operation *op, SetVector<Operation *> *forwardSlice,
}

void mlir::getForwardSlice(Value root, SetVector<Operation *> *forwardSlice,
TransitiveFilter filter) {
TransitiveFilter filter, bool inclusive) {
for (Operation *user : root.getUsers())
getForwardSliceImpl(user, forwardSlice, filter);

Expand Down Expand Up @@ -114,27 +116,30 @@ static void getBackwardSliceImpl(Operation *op,

void mlir::getBackwardSlice(Operation *op,
SetVector<Operation *> *backwardSlice,
TransitiveFilter filter) {
TransitiveFilter filter, bool inclusive) {
getBackwardSliceImpl(op, backwardSlice, filter);

// Don't insert the top level operation, we just queried on it and don't
// want it in the results.
backwardSlice->remove(op);
if (!inclusive) {
// Don't insert the top level operation, we just queried on it and don't
// want it in the results.
backwardSlice->remove(op);
}
}

void mlir::getBackwardSlice(Value root, SetVector<Operation *> *backwardSlice,
TransitiveFilter filter) {
TransitiveFilter filter, bool inclusive) {
if (Operation *definingOp = root.getDefiningOp()) {
getBackwardSlice(definingOp, backwardSlice, filter);
getBackwardSlice(definingOp, backwardSlice, filter, inclusive);
return;
}
Operation *bbAargOwner = root.cast<BlockArgument>().getOwner()->getParentOp();
getBackwardSlice(bbAargOwner, backwardSlice, filter);
getBackwardSlice(bbAargOwner, backwardSlice, filter, inclusive);
}

SetVector<Operation *> mlir::getSlice(Operation *op,
TransitiveFilter backwardFilter,
TransitiveFilter forwardFilter) {
TransitiveFilter forwardFilter,
bool inclusive) {
SetVector<Operation *> slice;
slice.insert(op);

Expand All @@ -145,12 +150,12 @@ SetVector<Operation *> mlir::getSlice(Operation *op,
auto *currentOp = (slice)[currentIndex];
// Compute and insert the backwardSlice starting from currentOp.
backwardSlice.clear();
getBackwardSlice(currentOp, &backwardSlice, backwardFilter);
getBackwardSlice(currentOp, &backwardSlice, backwardFilter, inclusive);
slice.insert(backwardSlice.begin(), backwardSlice.end());

// Compute and insert the forwardSlice starting from currentOp.
forwardSlice.clear();
getForwardSlice(currentOp, &forwardSlice, forwardFilter);
getForwardSlice(currentOp, &forwardSlice, forwardFilter, inclusive);
slice.insert(forwardSlice.begin(), forwardSlice.end());
++currentIndex;
}
Expand Down
70 changes: 50 additions & 20 deletions mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1718,18 +1718,19 @@ transform::PadOp::applyToOne(LinalgOp target,
transposePaddings.push_back(
extractFromI64ArrayAttr(transposeVector.cast<ArrayAttr>()));

LinalgPaddingOptions paddingOptions;
paddingOptions.setPaddingValues(paddingValues);
paddingOptions.setPaddingDimensions(
extractFromI64ArrayAttr(getPaddingDimensions()));
paddingOptions.setPackPaddings(packPaddings);
paddingOptions.setHoistPaddings(extractFromI64ArrayAttr(getHoistPaddings()));
paddingOptions.setTransposePaddings(transposePaddings);

FailureOr<LinalgOp> result =
tryApply<LinalgPaddingPattern>(target, paddingOptions);
IRRewriter rewriter(target->getContext());
LinalgOp paddedOp;
FailureOr<SmallVector<Value>> result = rewriteAsPaddedOp(
rewriter, target, extractFromI64ArrayAttr(getPaddingDimensions()),
paddingValues, packPaddings, paddedOp);
if (succeeded(result)) {
results.push_back(result->getOperation());
// We need to perform our own replacement here because this API is still
// used in patterns that "pad and hoist", for which the replacement values
// need to be different.
// TODO: clean this up and stop "pad and hoist" behavior more globally now
// that we have more composable abstractions.
rewriter.replaceOp(target, *result);
results.push_back(paddedOp);
return DiagnosedSilenceableFailure::success();
}

Expand All @@ -1756,15 +1757,6 @@ LogicalResult transform::PadOp::verify() {
<< getPaddingDimensions();
}

SmallVector<int64_t> hoistPaddings =
extractFromI64ArrayAttr(getHoistPaddings());
if (any_of(hoistPaddings,
[](int64_t hoistPadding) { return hoistPadding < 0; })) {
return emitOpError()
<< "expects hoist_paddings to contain positive integers, found "
<< getHoistPaddings();
}

ArrayAttr transposes = getTransposePaddings();
for (Attribute attr : transposes) {
SmallVector<int64_t> transpose = extractFromI64ArrayAttr(attr);
Expand All @@ -1779,6 +1771,44 @@ LogicalResult transform::PadOp::verify() {
return success();
}

//===---------------------------------------------------------------------===//
// HoistPadOp
//===---------------------------------------------------------------------===//

DiagnosedSilenceableFailure
transform::HoistPadOp::applyToOne(tensor::PadOp target,
transform::ApplyToEachResultList &results,
transform::TransformState &state) {
IRRewriter rewriter(target->getContext());
tensor::PadOp hoistedPadOp;
SmallVector<GenericOp> transposeOps;
// TODO: Pass rewriter down to hoistPaddingOnTensors, in a followup commit.
FailureOr<Value> result = hoistPaddingOnTensors(
target, getNumLoops(), getTranspose(), hoistedPadOp, transposeOps);
if (succeeded(result)) {
// We need to perform our own replacement here because this API is still
// used in patterns that "pad and hoist", for which the replacement values
// need to be different.
// TODO: clean this up and stop "pad and hoist" behavior more globally now
// that we have more composable abstractions.
rewriter.replaceOp(target, *result);
results.push_back(hoistedPadOp);
return DiagnosedSilenceableFailure::success();
}
return emitDefaultSilenceableFailure(target);
}

LogicalResult transform::HoistPadOp::verify() {
ArrayRef<int64_t> transpose = getTranspose();
auto sequence = llvm::to_vector(llvm::seq<int64_t>(0, transpose.size()));
if (!std::is_permutation(sequence.begin(), sequence.end(), transpose.begin(),
transpose.end())) {
return emitOpError() << "expects transpose to be a permutation, found "
<< getTranspose();
}
return success();
}

//===----------------------------------------------------------------------===//
// PromoteOp
//===----------------------------------------------------------------------===//
Expand Down
46 changes: 33 additions & 13 deletions mlir/lib/Dialect/Linalg/Transforms/HoistPadding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/Linalg/Transforms/HoistPadding.h"
#include "mlir/Analysis/SliceAnalysis.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
Expand All @@ -25,7 +24,9 @@
#include "mlir/IR/AsmState.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Dominance.h"

#include "mlir/IR/Matchers.h"
#include "mlir/Transforms/RegionUtils.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"

Expand Down Expand Up @@ -165,6 +166,30 @@ computeTransposedType(RankedTensorType rankedTensorType,
return transposedTensorType;
}

// Get all the ops in the backwards slice starting from `padOp` and that
// are dominated by the outermost enclosing loop.
// This also requires tracking ops defining values used in the region but
// defined above.
static void computeBackwardSlice(tensor::PadOp padOp,
scf::ForOp outermostEnclosingForOp,
SetVector<Operation *> &backwardSlice) {
DominanceInfo domInfo(outermostEnclosingForOp);
auto filter = [&](Operation *op) {
return domInfo.dominates(outermostEnclosingForOp, op) &&
!padOp->isProperAncestor(op);
};
// First, add the ops required to compute the region to the backwardSlice.
SetVector<Value> valuesDefinedAbove;
getUsedValuesDefinedAbove(padOp.getRegion(), padOp.getRegion(),
valuesDefinedAbove);
for (Value v : valuesDefinedAbove) {
getBackwardSlice(v, &backwardSlice, filter, /*inclusive=*/true);
}
// Then, add the backward slice from padOp itself.
getBackwardSlice(padOp.getOperation(), &backwardSlice, filter,
/*inclusive=*/true);
}

HoistingAnalysis::HoistingAnalysis(tensor::PadOp padOp, int numLoops) {
valid = false;

Expand Down Expand Up @@ -218,16 +243,9 @@ HoistingAnalysis::HoistingAnalysis(tensor::PadOp padOp, int numLoops) {
return;
}

// Get all the ops in the backwards slice starting from `padOp` and that
// are dominated by the outermost enclosing loop.
DominanceInfo domInfo(outermostEnclosingForOp);
getBackwardSlice(padOp.getOperation(), &backwardSlice, [&](Operation *op) {
return domInfo.dominates(outermostEnclosingForOp, op);
});
if (backwardSlice.empty())
computeBackwardSlice(padOp, outermostEnclosingForOp, backwardSlice);
if (backwardSlice.size() <= 1)
return;
// Add `padOp` itself to the backward slice.
backwardSlice.insert(padOp.getOperation());

// Remove all ops in the backward slice that are not used to index the padded
// tensor. In particular, keep `padOp`, `sliceOp`, and the loop and
Expand Down Expand Up @@ -394,9 +412,11 @@ static Value buildLoopIterationCount(OpBuilder &b, scf::ForOp outer,
ValueRange{ivVal, lbVal, stepVal});
}

FailureOr<Value> mlir::linalg::hoistPaddingOnTensors(
tensor::PadOp opToHoist, int numLoops, ArrayRef<int64_t> transposeVector,
tensor::PadOp &hoistedOp, SmallVectorImpl<GenericOp> &transposeOps) {
FailureOr<Value>
mlir::linalg::hoistPaddingOnTensors(tensor::PadOp opToHoist, int64_t numLoops,
ArrayRef<int64_t> transposeVector,
tensor::PadOp &hoistedOp,
SmallVectorImpl<GenericOp> &transposeOps) {
LLVM_DEBUG(DBGS() << "Try to hoist " << *(opToHoist) << " by " << numLoops
<< " loops\n");
HoistingAnalysis analysis(opToHoist, numLoops);
Expand Down
1,932 changes: 989 additions & 943 deletions mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ transform::LoopPeelOp::applyToOne(scf::ForOp target,
// "the loop trip count is divisible by the step"
// is valid.
LogicalResult status =
scf::peelAndCanonicalizeForLoop(rewriter, target, result);
scf::peelForLoopAndSimplifyBounds(rewriter, target, result);
// TODO: Return both the peeled loop and the remainder loop.
results.push_back(failed(status) ? target : result);
return DiagnosedSilenceableFailure::success();
Expand Down
8 changes: 4 additions & 4 deletions mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ static void rewriteAffineOpAfterPeeling(RewriterBase &rewriter, ForOp forOp,
});
}

LogicalResult mlir::scf::peelAndCanonicalizeForLoop(RewriterBase &rewriter,
ForOp forOp,
ForOp &partialIteration) {
LogicalResult mlir::scf::peelForLoopAndSimplifyBounds(RewriterBase &rewriter,
ForOp forOp,
ForOp &partialIteration) {
Value previousUb = forOp.getUpperBound();
Value splitBound;
if (failed(peelForLoop(rewriter, forOp, partialIteration, splitBound)))
Expand Down Expand Up @@ -218,7 +218,7 @@ struct ForLoopPeelingPattern : public OpRewritePattern<ForOp> {
}
// Apply loop peeling.
scf::ForOp partialIteration;
if (failed(peelAndCanonicalizeForLoop(rewriter, forOp, partialIteration)))
if (failed(peelForLoopAndSimplifyBounds(rewriter, forOp, partialIteration)))
return failure();
// Apply label, so that the same loop is not rewritten a second time.
rewriter.updateRootInPlace(partialIteration, [&]() {
Expand Down
3 changes: 0 additions & 3 deletions mlir/python/mlir/dialects/_structured_transform_ops_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ def __init__(self,
Sequence[Attribute]]] = None,
padding_dimensions: OptionalIntList = None,
pack_paddings: OptionalIntList = None,
hoist_paddings: OptionalIntList = None,
transpose_paddings: Optional[Union[ArrayAttr, Sequence[Union[
ArrayAttr, IntOrAttrList]]]] = None,
loc=None,
Expand All @@ -180,15 +179,13 @@ def __init__(self,
padding_values_attr = _get_array_attr(padding_values)
padding_dimensions_attr = _get_int_array_attr(padding_dimensions)
pack_paddings_attr = _get_int_array_attr(pack_paddings)
hoist_paddings_attr = _get_int_array_attr(hoist_paddings)
transpose_paddings_attr = _get_int_int_array_attr(transpose_paddings)
super().__init__(
pdl_operation_type,
_get_op_result_or_value(target),
padding_values=padding_values_attr,
padding_dimensions=padding_dimensions_attr,
pack_paddings=pack_paddings_attr,
hoist_paddings=hoist_paddings_attr,
transpose_paddings=transpose_paddings_attr,
loc=loc,
ip=ip)
Expand Down
151 changes: 151 additions & 0 deletions mlir/test/Dialect/Linalg/transform-op-hoist-pad.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// RUN: mlir-opt --test-transform-dialect-interpreter -canonicalize -split-input-file --verify-diagnostics %s | FileCheck %s

func.func @pad_and_hoist_rhs(
%arg0: tensor<24x12xf32>, %arg1: tensor<12x25xf32>, %arg2: tensor<24x25xf32>)
-> tensor<24x25xf32>
{
// expected-note @below {{payload operation}}
%0 = linalg.matmul ins(%arg0, %arg1 : tensor<24x12xf32>, tensor<12x25xf32>) outs(%arg2 : tensor<24x25xf32>) -> tensor<24x25xf32>
func.return %0 : tensor<24x25xf32>
}

transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%matmul = transform.structured.match ops{["linalg.matmul"]} in %arg1
: (!pdl.operation) -> !pdl.operation


%matmul_l1, %loops_l1 = transform.structured.tile_to_scf_for %matmul [5]

%matmul_padded = transform.structured.pad %matmul_l1 {
padding_values=[0.0: f32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2]
}

// In this case, the pad op is actually empty: we only tile the first dimension
// and it does not have an impact on the RHS operand.
// expected-error @below {{incompatible payload operation name}}
%pad = transform.get_producer_of_operand %matmul_padded[1]
: (!pdl.operation) -> !transform.op<"tensor.pad">

// We do not even reach this transform op.
transform.structured.hoist_pad %pad by 1 loops
: (!transform.op<"tensor.pad">) -> !pdl.operation
}

// -----

func.func @pad_and_hoist_init(
%arg0: tensor<24x12xf32>, %arg1: tensor<12x25xf32>, %arg2: tensor<24x25xf32>)
-> tensor<24x25xf32>
{
// expected-note @below {{when applied to this op}}
%0 = linalg.matmul ins(%arg0, %arg1 : tensor<24x12xf32>, tensor<12x25xf32>) outs(%arg2 : tensor<24x25xf32>) -> tensor<24x25xf32>
func.return %0 : tensor<24x25xf32>
}

transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%matmul = transform.structured.match ops{["linalg.matmul"]} in %arg1
: (!pdl.operation) -> !pdl.operation


%matmul_l1, %loops_l1 = transform.structured.tile_to_scf_for %matmul [5]

%matmul_padded = transform.structured.pad %matmul_l1 {
padding_values=[0.0: f32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2]
}

%pad = transform.get_producer_of_operand %matmul_padded[2]
: (!pdl.operation) -> !transform.op<"tensor.pad">

// We do not know yet how to hoist the init.
// expected-error @below {{transform.structured.hoist_pad failed to apply}}
transform.structured.hoist_pad %pad by 1 loops
: (!transform.op<"tensor.pad">) -> !pdl.operation
}

// -----

// CHECK-LABEL: pad_and_hoist_lhs
func.func @pad_and_hoist_lhs(
%arg0: tensor<24x12xf32>, %arg1: tensor<12x25xf32>, %arg2: tensor<24x25xf32>)
-> tensor<24x25xf32>
{
// CHECK: %[[PACKED:.*]] = scf.for %{{.*}} -> (tensor<5x5x12xf32>) {
// CHECK: tensor.pad %{{.*}}
// CHECK: : tensor<?x12xf32> to tensor<5x12xf32>
// CHECK: tensor.insert_slice %{{.*}} into %{{.*}}[%{{.*}}, 0, 0] [1, 5, 12] [1, 1, 1]
// CHECK-SAME: : tensor<5x12xf32> into tensor<5x5x12xf32>
// CHECK: scf.for %{{.*}} -> (tensor<24x25xf32>) {
// CHECK: %[[PADDED:.*]] = tensor.extract_slice %[[PACKED]][%{{.*}}, 0, 0] [1, 5, 12] [1, 1, 1]
// CHECK-SAME: : tensor<5x5x12xf32> to tensor<5x12xf32>
// CHECK: linalg.matmul ins(%[[PADDED]]
%0 = linalg.matmul ins(%arg0, %arg1 : tensor<24x12xf32>, tensor<12x25xf32>) outs(%arg2 : tensor<24x25xf32>) -> tensor<24x25xf32>
func.return %0 : tensor<24x25xf32>
}

transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%matmul = transform.structured.match ops{["linalg.matmul"]} in %arg1
: (!pdl.operation) -> !pdl.operation


%matmul_l1, %loops_l1 = transform.structured.tile_to_scf_for %matmul [5]

%matmul_padded = transform.structured.pad %matmul_l1 {
padding_values=[0.0: f32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2]
}

%pad = transform.get_producer_of_operand %matmul_padded[0]
: (!pdl.operation) -> !pdl.operation

transform.structured.hoist_pad %pad by 1 loops
: (!pdl.operation) -> !pdl.operation
}

// -----

// CHECK-LABEL: pad_and_hoist_lhs_transpose
func.func @pad_and_hoist_lhs_transpose(
%arg0: tensor<24x12xf32>, %arg1: tensor<12x25xf32>, %arg2: tensor<24x25xf32>)
-> tensor<24x25xf32>
{
// CHECK: %[[PACKED:.*]] = scf.for %{{.*}} -> (tensor<5x12x5xf32>) {
// CHECK: tensor.pad %{{.*}}
// CHECK: : tensor<?x12xf32> to tensor<5x12xf32>
// CHECK: linalg.generic
// CHECK: -> tensor<12x5xf32>
// CHECK: tensor.insert_slice %{{.*}} into %{{.*}}[%{{.*}}, 0, 0] [1, 12, 5] [1, 1, 1]
// CHECK-SAME: : tensor<12x5xf32> into tensor<5x12x5xf32>
// CHECK: scf.for %{{.*}} -> (tensor<24x25xf32>) {
// CHECK: %[[PADDED:.*]] = tensor.extract_slice %[[PACKED]][%{{.*}}, 0, 0] [1, 12, 5] [1, 1, 1]
// CHECK-SAME: : tensor<5x12x5xf32> to tensor<12x5xf32>
// CHECK: %[[TRANSPOSED:.*]] = linalg.generic
// CHECK: -> tensor<5x12xf32>
// CHECK: linalg.matmul ins(%[[TRANSPOSED]]
%0 = linalg.matmul ins(%arg0, %arg1 : tensor<24x12xf32>, tensor<12x25xf32>) outs(%arg2 : tensor<24x25xf32>) -> tensor<24x25xf32>
func.return %0 : tensor<24x25xf32>
}

transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%matmul = transform.structured.match ops{["linalg.matmul"]} in %arg1
: (!pdl.operation) -> !pdl.operation


%matmul_l1, %loops_l1 = transform.structured.tile_to_scf_for %matmul [5]

%matmul_padded = transform.structured.pad %matmul_l1 {
padding_values=[0.0: f32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2]
}

%pad = transform.get_producer_of_operand %matmul_padded[0]
: (!pdl.operation) -> !pdl.operation

transform.structured.hoist_pad %pad by 1 loops, transpose by [1, 0]
: (!pdl.operation) -> !pdl.operation
}
30 changes: 25 additions & 5 deletions mlir/test/Dialect/Linalg/transform-op-pad.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ func.func @static_sizes_output_divisible(%arg0: tensor<24x12xf32>,
transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!pdl.operation) -> !pdl.operation
%1 = transform.structured.pad %0 {padding_values=[0.0 : f32, 0.0 : f32, 0.0 : f32], padding_dimensions=[0, 1, 2], pack_paddings=[1, 1, 0]}
%1 = transform.structured.pad %0 {
padding_values=[0.0 : f32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2],
pack_paddings=[1, 1, 0]
}
}

// -----
Expand Down Expand Up @@ -72,7 +76,11 @@ func.func @static_sizes_output_divisible_on_empty_op(%arg0: tensor<24x12xf32>,
transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!pdl.operation) -> !pdl.operation
%1 = transform.structured.pad %0 {padding_values=[0.0 : f32, 0.0 : f32, 0.0 : f32], padding_dimensions=[0, 1, 2], pack_paddings=[1, 1, 0]}
%1 = transform.structured.pad %0 {
padding_values=[0.0 : f32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2],
pack_paddings=[1, 1, 0]
}
}

// -----
Expand All @@ -89,7 +97,11 @@ transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!pdl.operation) -> !pdl.operation
// expected-error @below {{op expects a padding value of type 'f32', got 0 : i32}}
%1 = transform.structured.pad %0 {padding_values=[0: i32, 0.0 : f32, 0.0 : f32], padding_dimensions=[0, 1, 2], pack_paddings=[1, 1, 0]}
%1 = transform.structured.pad %0 {
padding_values=[0: i32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2],
pack_paddings=[1, 1, 0]
}
}

// -----
Expand All @@ -106,7 +118,11 @@ transform.sequence failures(propagate) {
^bb1(%arg1: !pdl.operation):
%0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!pdl.operation) -> !pdl.operation
// expected-error @below {{expects a padding that parses to 'f32', got "foo"}}
%1 = transform.structured.pad %0 {padding_values=["foo", 0.0 : f32, 0.0 : f32], padding_dimensions=[0, 1, 2], pack_paddings=[1, 1, 0]}
%1 = transform.structured.pad %0 {
padding_values=["foo", 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2],
pack_paddings=[1, 1, 0]
}
}

// -----
Expand All @@ -125,5 +141,9 @@ transform.sequence failures(suppress) {
%0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!pdl.operation) -> !pdl.operation
// This error is silenceable and is not reported by this transform
// {{transform.structured.pad failed to apply}}
%1 = transform.structured.pad %0 {padding_values=[0.0 : f32, 0.0 : f32, 0.0 : f32], padding_dimensions=[0, 1, 2], pack_paddings=[1, 1, 0]}
%1 = transform.structured.pad %0 {
padding_values=[0.0 : f32, 0.0 : f32, 0.0 : f32],
padding_dimensions=[0, 1, 2],
pack_paddings=[1, 1, 0]
}
}
8 changes: 0 additions & 8 deletions mlir/test/Dialect/Linalg/transform-ops-invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ transform.sequence failures(propagate) {

// -----

transform.sequence failures(propagate) {
^bb0(%arg0: !pdl.operation):
// expected-error@below {{expects hoist_paddings to contain positive integers, found [1, -7]}}
transform.structured.pad %arg0 {hoist_paddings=[1, -7]}
}

// -----

transform.sequence failures(propagate) {
^bb0(%arg0: !pdl.operation):
// expected-error@below {{expects transpose_paddings to be a permutation, found [1, 1]}}
Expand Down
1 change: 0 additions & 1 deletion mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/Linalg/IR/Linalg.h"
#include "mlir/Dialect/Linalg/Passes.h"
#include "mlir/Dialect/Linalg/Transforms/HoistPadding.h"
#include "mlir/Dialect/Linalg/Transforms/Hoisting.h"
#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
#include "mlir/Dialect/Linalg/Utils/Utils.h"
Expand Down
2 changes: 1 addition & 1 deletion mlir/test/python/dialects/transform_structured_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def testPad():
# CHECK-DAG: padding_values = [4.200000e+01 : f32]
# CHECK-DAG: padding_dimensions = [1]
# CHECK-DAG: transpose_paddings = {{\[}}[1, 0]]
# (hoist_paddings and pack_paddings have default values)
# (pack_paddings has default values)

@run
def testScalarize():
Expand Down