[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:
@@ -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>,
|
||||
|
||||
@@ -14,6 +14,8 @@ add_mlir_dialect_library(MLIRTransformDialect
|
||||
LINK_LIBS PUBLIC
|
||||
MLIRCastInterfaces
|
||||
MLIRIR
|
||||
MLIRLLVMCommonConversion
|
||||
MLIRLLVMDialect
|
||||
MLIRLoopLikeInterface
|
||||
MLIRParser
|
||||
MLIRPass
|
||||
|
||||
@@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -10601,6 +10601,8 @@ cc_library(
|
||||
":ControlFlowInterfaces",
|
||||
":IR",
|
||||
":LoopLikeInterface",
|
||||
":LLVMCommonConversion",
|
||||
":LLVMDialect",
|
||||
":Pass",
|
||||
":Rewrite",
|
||||
":SideEffectInterfaces",
|
||||
|
||||
Reference in New Issue
Block a user