mirror of https://github.com/llvm/circt.git
[OM] Add OM tuple operations (#5878)
This commit adds `tuple_create` and `tuple_get` operations.
This commit is contained in:
parent
08778859fc
commit
e3381acf15
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue