[OM] Add OM tuple operations (#5878)

This commit adds `tuple_create` and `tuple_get` operations.
This commit is contained in:
Hideto Ueno 2023-08-21 14:01:30 +09:00 committed by GitHub
parent 08778859fc
commit e3381acf15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 127 additions and 0 deletions

View File

@ -18,6 +18,7 @@
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/InferTypeOpInterface.h"
#define GET_OP_CLASSES
#include "circt/Dialect/OM/OM.h.inc"

View File

@ -14,8 +14,10 @@
#define CIRCT_DIALECT_OM_OMOPS_TD
include "circt/Dialect/OM/OMOpInterfaces.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/BuiltinTypes.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/SymbolInterfaces.td"
@ -195,4 +197,68 @@ def ListCreateOp : OMOp<"list_create", [Pure, SameTypeOperands]> {
let hasCustomAssemblyFormat = 1;
}
def TupleCreateOp : OMOp<"tuple_create", [Pure, InferTypeOpInterface]> {
let summary = "Create a tuple of values";
let description = [{
Create a tuple from a sequence of inputs.
```
%tuple = om.tuple_create %a, %b, %c : !om.ref, !om.string, !om.list<i32>
```
}];
let arguments = (ins Variadic<AnyType>:$inputs);
let results = (outs
TupleOf<[AnyType]>:$result
);
let assemblyFormat = [{
$inputs `:` type($inputs) attr-dict
}];
let extraClassDeclaration = [{
// Implement InferTypeOpInterface.
static ::mlir::LogicalResult inferReturnTypes(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
::mlir::OpaqueProperties,
::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes);
}];
}
def TupleGetOp : OMOp<"tuple_get", [Pure, InferTypeOpInterface]> {
let summary = "Extract a value from a tuple";
let description = [{
Extract a value from a tuple.
```
%value = om.tuple_get %a[0] : tuple<!om.ref, !om.string, !om.list<i32>>
```
}];
let arguments = (ins
TupleOf<[AnyType]>:$input,
I32Attr:$index
);
let results = (outs
AnyType:$result
);
let assemblyFormat = [{
$input `[` $index `]` `:` type($input) attr-dict
}];
let extraClassDeclaration = [{
// Implement InferTypeOpInterface.
static ::mlir::LogicalResult inferReturnTypes(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
::mlir::OpaqueProperties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes);
}];
}
#endif // CIRCT_DIALECT_OM_OMOPS_TD

View File

@ -380,6 +380,47 @@ ParseResult circt::om::ListCreateOp::parse(OpAsmParser &parser,
return success();
}
//===----------------------------------------------------------------------===//
// TupleCreateOp
//===----------------------------------------------------------------------===//
LogicalResult TupleCreateOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
DictionaryAttr attributes, OpaqueProperties, RegionRange regions,
llvm::SmallVectorImpl<Type> &inferredReturnTypes) {
::llvm::SmallVector<Type> types;
for (auto op : operands)
types.push_back(op.getType());
inferredReturnTypes.push_back(TupleType::get(context, types));
return success();
}
//===----------------------------------------------------------------------===//
// TupleGetOp
//===----------------------------------------------------------------------===//
LogicalResult TupleGetOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
DictionaryAttr attributes, OpaqueProperties, RegionRange regions,
llvm::SmallVectorImpl<Type> &inferredReturnTypes) {
auto idx = attributes.getAs<IntegerAttr>("index");
if (operands.empty() || !idx)
return failure();
auto tupleTypes = operands[0].getType().cast<TupleType>().getTypes();
if (tupleTypes.size() <= idx.getValue().getLimitedValue()) {
if (location)
mlir::emitError(*location,
"tuple index out-of-bounds, must be less than ")
<< tupleTypes.size() << " but got "
<< idx.getValue().getLimitedValue();
return failure();
}
inferredReturnTypes.push_back(tupleTypes[idx.getValue().getLimitedValue()]);
return success();
}
//===----------------------------------------------------------------------===//
// TableGen generated logic.
//===----------------------------------------------------------------------===//

View File

@ -102,3 +102,10 @@ om.class @ListCreate() {
// expected-error @+1 {{map key type must be either string or integer but got '!om.list<!om.string>'}}
om.class @Map(%map: !om.map<!om.list<!om.string>, !om.string>) {
}
// -----
om.class @Tuple(%tuple: tuple<i1, !om.string>) {
// expected-error @+1 {{tuple index out-of-bounds, must be less than 2 but got 2}}
%val = om.tuple_get %tuple[2] : tuple<i1, !om.string>
}

View File

@ -171,3 +171,15 @@ om.class @StringConstant() {
om.class @Map(%map: !om.map<!om.string, !om.string>) {
om.class.field @field, %map : !om.map<!om.string, !om.string>
}
// CHECK-LABEL: @Tuple
om.class @Tuple(%int: i1, %str: !om.string) {
// CHECK: %[[tuple:.+]] = om.tuple_create %int, %str : i1, !om.string
%tuple = om.tuple_create %int, %str : i1, !om.string
// CHECK-NEXT: om.class.field @tuple, %[[tuple]] : tuple<i1, !om.string>
om.class.field @tuple, %tuple : tuple<i1, !om.string>
// CHECK-NEXT: %[[tuple_get:.+]] = om.tuple_get %[[tuple]][1] : tuple<i1, !om.string>
%val = om.tuple_get %tuple[1] : tuple<i1, !om.string>
// CHECK-NEXT: om.class.field @val, %[[tuple_get]] : !om.string
om.class.field @val, %val : !om.string
}