[mlir][transform] Add ApplyToLLVMConversionPatternsOp

This op populates conversion patterns by querying the
ConvertToLLVMPatternInterface. Only dialects that support this interface
are supported.

Differential Revision: https://reviews.llvm.org/D157487
This commit is contained in:
Matthias Springer
2023-08-09 12:18:23 +02:00
parent c2a8f22043
commit 0bb4d4d32f
6 changed files with 127 additions and 0 deletions

View File

@@ -234,6 +234,25 @@ def ApplyConversionPatternsOp : TransformDialectOp<"apply_conversion_patterns",
}];
}
def ApplyToLLVMConversionPatternsOp : Op<Transform_Dialect,
"apply_conversion_patterns.dialect_to_llvm",
[DeclareOpInterfaceMethods<ConversionPatternDescriptorOpInterface,
["verifyTypeConverter"]>]> {
let description = [{
Collects patterns that convert ops from the specified dialect to LLVM
dialect ops. These patterns require an "LLVMTypeConverter".
Note: Only dialects that implement the `ConvertToLLVMPatternInterface` are
supported. Any conversion target modifications by interface implementations
are currently ignored. The conversion target is fully specified by the
enclosing "apply_conversion_patterns" op.
}];
let arguments = (ins StrAttr:$dialect_name);
let assemblyFormat = "$dialect_name attr-dict";
let hasVerifier = 1;
}
def ApplyDeadCodeEliminationOp : TransformDialectOp<"apply_dce",
[TransformOpInterface, TransformEachOpTrait,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,

View File

@@ -14,6 +14,8 @@ add_mlir_dialect_library(MLIRTransformDialect
LINK_LIBS PUBLIC
MLIRCastInterfaces
MLIRIR
MLIRLLVMCommonConversion
MLIRLLVMDialect
MLIRLoopLikeInterface
MLIRParser
MLIRPass

View File

@@ -8,6 +8,8 @@
#include "mlir/Dialect/Transform/IR/TransformOps.h"
#include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
#include "mlir/Dialect/Transform/IR/MatchInterfaces.h"
#include "mlir/Dialect/Transform/IR/TransformAttrs.h"
#include "mlir/Dialect/Transform/IR/TransformDialect.h"
@@ -642,6 +644,43 @@ void transform::ApplyConversionPatternsOp::build(
}
}
//===----------------------------------------------------------------------===//
// ApplyToLLVMConversionPatternsOp
//===----------------------------------------------------------------------===//
void transform::ApplyToLLVMConversionPatternsOp::populatePatterns(
TypeConverter &typeConverter, RewritePatternSet &patterns) {
Dialect *dialect = getContext()->getLoadedDialect(getDialectName());
assert(dialect && "expected that dialect is loaded");
auto iface = cast<ConvertToLLVMPatternInterface>(dialect);
// ConversionTarget is currently ignored because the enclosing
// apply_conversion_patterns op sets up its own ConversionTarget.
ConversionTarget target(*getContext());
iface->populateConvertToLLVMConversionPatterns(
target, static_cast<LLVMTypeConverter &>(typeConverter), patterns);
}
LogicalResult transform::ApplyToLLVMConversionPatternsOp::verifyTypeConverter(
transform::TypeConverterBuilderOpInterface builder) {
if (builder.getTypeConverterType() != "LLVMTypeConverter")
return emitOpError("expected LLVMTypeConverter");
return success();
}
LogicalResult transform::ApplyToLLVMConversionPatternsOp::verify() {
Dialect *dialect = getContext()->getLoadedDialect(getDialectName());
if (!dialect)
return emitOpError("unknown dialect or dialect not loaded: ")
<< getDialectName();
auto iface = dyn_cast<ConvertToLLVMPatternInterface>(dialect);
if (!iface)
return emitOpError(
"dialect does not implement ConvertToLLVMPatternInterface or "
"extension was not loaded: ")
<< getDialectName();
return success();
}
//===----------------------------------------------------------------------===//
// ApplyLoopInvariantCodeMotionOp
//===----------------------------------------------------------------------===//

View File

@@ -256,3 +256,23 @@ transform.sequence failures(propagate) {
// Verify that the returned handle is usable.
transform.test_print_remark_at_operand %1, "transformed" : !transform.any_op
}
// -----
// CHECK-LABEL: func @lower_to_llvm
// CHECK-NOT: memref.alloc
// CHECK: llvm.call @malloc
func.func @lower_to_llvm() {
%0 = memref.alloc() : memref<2048xi8>
return
}
transform.sequence failures(propagate) {
^bb1(%arg1: !transform.any_op):
%0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
transform.apply_conversion_patterns to %0 {
transform.apply_conversion_patterns.dialect_to_llvm "memref"
} with type_converter {
transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter
} {legal_dialects = ["func", "llvm"]} : !transform.any_op
}

View File

@@ -279,3 +279,48 @@ transform.sequence failures(propagate) {
transform.apply_conversion_patterns.transform.test_conversion_patterns
} {illegal_ops = ["test.foo"]} : !transform.any_op
}
// -----
transform.sequence failures(propagate) {
^bb1(%arg1: !transform.any_op):
%0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
transform.apply_conversion_patterns to %0 {
// expected-error @below{{expected LLVMTypeConverter}}
transform.apply_conversion_patterns.dialect_to_llvm "test"
} with type_converter {
transform.apply_conversion_patterns.transform.test_type_converter
} {illegal_ops = ["test.foo"],
legal_ops = ["func.func", "func.return", "test.new_op"]}
: !transform.any_op
}
// -----
transform.sequence failures(propagate) {
^bb1(%arg1: !transform.any_op):
%0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
transform.apply_conversion_patterns to %0 {
// expected-error @below{{unknown dialect or dialect not loaded: this_dialect_does_not_exist}}
transform.apply_conversion_patterns.dialect_to_llvm "this_dialect_does_not_exist"
} with type_converter {
transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter
} {illegal_ops = ["test.foo"],
legal_ops = ["func.func", "func.return", "test.new_op"]}
: !transform.any_op
}
// -----
transform.sequence failures(propagate) {
^bb1(%arg1: !transform.any_op):
%0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
transform.apply_conversion_patterns to %0 {
// expected-error @below{{dialect does not implement ConvertToLLVMPatternInterface or extension was not loaded: transform}}
transform.apply_conversion_patterns.dialect_to_llvm "transform"
} with type_converter {
transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter
} {illegal_ops = ["test.foo"],
legal_ops = ["func.func", "func.return", "test.new_op"]}
: !transform.any_op
}

View File

@@ -10601,6 +10601,8 @@ cc_library(
":ControlFlowInterfaces",
":IR",
":LoopLikeInterface",
":LLVMCommonConversion",
":LLVMDialect",
":Pass",
":Rewrite",
":SideEffectInterfaces",