The current implementation uses a discrete "pdl_interp.inferred_types" operation, which acts as a "fake" handle to a type range. This op is used as a signal to pdl_interp.create_operation that types should be inferred. This is terribly awkward and clunky though: * This op doesn't have a byte code representation, and its conversion to bytecode kind of assumes that it is only used in a certain way. The current lowering is also broken and seemingly untested. * Given that this is a different operation, it gives off the assumption that it can be used multiple times, or that after the first use the value contains the inferred types. This isn't the case though, the resultant type range can never actually be used as a type range. This commit refactors the representation by removing the discrete InferredTypesOp, and instead adds a UnitAttr to pdl_interp.CreateOperation that signals when the created operations should infer their types. This leads to a much much cleaner abstraction, a more optimal bytecode lowering, and also allows for better error handling and diagnostics when a created operation doesn't actually support type inferrence. Differential Revision: https://reviews.llvm.org/D124587
76 lines
2.1 KiB
MLIR
76 lines
2.1 KiB
MLIR
// RUN: mlir-opt -split-input-file %s | mlir-opt
|
|
// Verify the printed output can be parsed.
|
|
// RUN: mlir-opt %s | mlir-opt
|
|
// Verify the generic form can be parsed.
|
|
// RUN: mlir-opt -mlir-print-op-generic %s | mlir-opt
|
|
|
|
// -----
|
|
|
|
// Unused operation to force loading the `arithmetic` dialect for the
|
|
// test of type inferrence.
|
|
arith.constant true
|
|
|
|
func.func @operations(%attribute: !pdl.attribute,
|
|
%input: !pdl.value,
|
|
%type: !pdl.type) {
|
|
// attributes, operands, and results
|
|
%op0 = pdl_interp.create_operation "foo.op"(%input : !pdl.value) {"attr" = %attribute} -> (%type : !pdl.type)
|
|
|
|
// attributes, and results
|
|
%op1 = pdl_interp.create_operation "foo.op" {"attr" = %attribute} -> (%type : !pdl.type)
|
|
|
|
// attributes
|
|
%op2 = pdl_interp.create_operation "foo.op" {"attr" = %attribute, "attr1" = %attribute}
|
|
|
|
// operands, and results
|
|
%op3 = pdl_interp.create_operation "foo.op"(%input : !pdl.value) -> (%type : !pdl.type)
|
|
|
|
// inferred results
|
|
%op4 = pdl_interp.create_operation "arith.constant" -> <inferred>
|
|
|
|
pdl_interp.finalize
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @extract(%attrs : !pdl.range<attribute>, %ops : !pdl.range<operation>, %types : !pdl.range<type>, %vals: !pdl.range<value>) {
|
|
// attribute at index 0
|
|
%attr = pdl_interp.extract 0 of %attrs : !pdl.attribute
|
|
|
|
// operation at index 1
|
|
%op = pdl_interp.extract 1 of %ops : !pdl.operation
|
|
|
|
// type at index 2
|
|
%type = pdl_interp.extract 2 of %types : !pdl.type
|
|
|
|
// value at index 3
|
|
%val = pdl_interp.extract 3 of %vals : !pdl.value
|
|
|
|
pdl_interp.finalize
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @foreach(%ops: !pdl.range<operation>) {
|
|
// iterate over a range of operations
|
|
pdl_interp.foreach %op : !pdl.operation in %ops {
|
|
%val = pdl_interp.get_result 0 of %op
|
|
pdl_interp.continue
|
|
} -> ^end
|
|
|
|
^end:
|
|
pdl_interp.finalize
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @users(%value: !pdl.value, %values: !pdl.range<value>) {
|
|
// all the users of a single value
|
|
%ops1 = pdl_interp.get_users of %value : !pdl.value
|
|
|
|
// all the users of all the values in a range
|
|
%ops2 = pdl_interp.get_users of %values : !pdl.range<value>
|
|
|
|
pdl_interp.finalize
|
|
}
|