diff --git a/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsOps.td b/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsOps.td index eb719d86d715..e6b6eec8678e 100644 --- a/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsOps.td +++ b/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsOps.td @@ -79,46 +79,38 @@ def Iterators_PrintOp : Iterators_Base_Op<"print", [ // High-level iterators //===----------------------------------------------------------------------===// -/// Verifies that the element types of nested arrays in the $value array -/// correspond to the types of the LLVM-struct element type of the $result -/// Stream. -def Iterators_ValueMatchesElementTypePred - : CPred<[{$value.dyn_cast().size() == 0 || - $result.getType().dyn_cast().getElementType() == - ::mlir::LLVM::LLVMStructType::getLiteral( - $result.getType().getContext(), - ::llvm::SmallVector( - ::llvm::map_range( - $value.dyn_cast<::mlir::ArrayAttr>().begin()->dyn_cast<::mlir::ArrayAttr>(), - [](Attribute attr) { return attr.cast().getType(); } - ) - ) - )}]>; -def Iterators_ValueMatchesElementType - : PredOpTrait<"value type matches return type", - Iterators_ValueMatchesElementTypePred>; - -def Iterators_ConstantStreamOp : Iterators_Op<"constantstream", - [Iterators_ValueMatchesElementType, - DeclareOpInterfaceMethods]> { +def Iterators_ConstantStreamOp : Iterators_Op<"constantstream", [ + PredOpTrait<"element type of return type must be tuple with matching types", + CPred<[{ + $value.cast<::mlir::ArrayAttr>().size () == 0 || + TupleType::get( + $value.getContext(), + ::llvm::SmallVector( + ::llvm::map_range( + $value.cast<::mlir::ArrayAttr>().begin()->cast<::mlir::ArrayAttr>(), + [](Attribute attr) { return attr.cast().getType(); } + ))) == + $result.getType().cast().getElementType()}]>>, + DeclareOpInterfaceMethods]> { let summary = "Produce a statically defined stream of elements"; let description = [{ - Produces a stream of LLVM structs given in the array of arrays attribute - (each inner array being returned as a literal LLVM struct with the values - and types of the elements of that array). The inner arrays all have to have - matching types, i.e., the element at position i has to be the same for all - inner arrays, and the element type of the return Stream has to be the - corresponding literal LLVM struct. An empty array is allowed (in which case - the return Stream does not need to match anything). + Produces a stream of tuples given in the array of arrays attribute (each + inner array being returned as a built-in tuple with the values and types of + the elements of that array). The inner arrays all have to have matching + types, i.e., the element at position i has to be the same for all inner + arrays, and the element type of the return Stream has to be the + corresponding tuple tpye. An empty array is allowed (in which case the + return Stream does not need to match anything). Example: ```mlir %constantstream = "iterators.constantstream"() { value = [[42 : i32]] } : - () -> (!iterators.stream>) + () -> (!iterators.stream>) ``` }]; + // TODO(ingomueller): Devise a lowering that allows to return non-LLVM types. let arguments = (ins Iterators_HomogeneouslyTypedLLVMNumericArrayArrayAttr:$value); - let results = (outs Iterators_StreamOfLLVMStructOfNumerics:$result); + let results = (outs Iterators_StreamOfPrintableTuples:$result); let extraClassDefinition = [{ /// Implement OpAsmOpInterface. void $cppClass::getAsmResultNames( diff --git a/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsTypes.td b/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsTypes.td index 1b32cddc541e..4431516a5bff 100644 --- a/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsTypes.td +++ b/experimental/iterators/include/iterators/Dialect/Iterators/IR/IteratorsTypes.td @@ -230,6 +230,10 @@ class Iterators_StreamOf def Iterators_StreamOfLLVMStructOfNumerics : Iterators_StreamOf; +/// An Iterators stream of tuples of printable types. +def Iterators_StreamOfPrintableTuples + : Iterators_StreamOf; + /// An Iterators stream of printable elements. def Iterators_StreamOfPrintableElements : Iterators_StreamOf; diff --git a/experimental/iterators/lib/Conversion/IteratorsToLLVM/IteratorsToLLVM.cpp b/experimental/iterators/lib/Conversion/IteratorsToLLVM/IteratorsToLLVM.cpp index 9f97ac87bd68..5ff0ad927a3d 100644 --- a/experimental/iterators/lib/Conversion/IteratorsToLLVM/IteratorsToLLVM.cpp +++ b/experimental/iterators/lib/Conversion/IteratorsToLLVM/IteratorsToLLVM.cpp @@ -408,20 +408,22 @@ static GlobalOp buildGlobalData(ConstantStreamOp op, OpBuilder &builder, /// %0 = iterators.extractvalue %arg0[0] : !iterators.state /// %c4_i32 = arith.constant 4 : i32 /// %1 = arith.cmpi slt, %0, %c4_i32 : i32 -/// %2:2 = scf.if %1 -> (!iterators.state, !element_type) { +/// %2:2 = scf.if %1 -> (!iterators.state, !struct_tpe) { /// %c1_i32 = arith.constant 1 : i32 /// %3 = arith.addi %0, %c1_i32 : i32 /// %4 = iterators.insertvalue %3 into %arg0[0] : !iterators.state /// %5 = llvm.mlir.addressof @iterators.constant_stream_data.0 : !llvm.ptr /// %6 = llvm.getelementptr %5[%0, 0] : -/// (!llvm.ptr>, i32, i32) -/// -> !llvm.ptr, !element_type -/// %7 = llvm.load %6 : !llvm.ptr -> !element_type -/// scf.yield %4, %7 : !iterators.state, !element_type +/// (!llvm.ptr>, i32, i32) +/// -> !llvm.ptr, !struct_type +/// %7 = llvm.load %6 : !llvm.ptr -> !struct_type +/// scf.yield %4, %7 : !iterators.state, !struct_type /// } else { -/// %3 = llvm.mlir.undef : !element_type -/// scf.yield %arg0, %3 : !iterators.state, !element_type +/// %4 = llvm.mlir.undef : !struct_tpe +/// scf.yield %arg0, %3 : !iterators.state, !struct_tpe /// } +/// %3 = llvm.extractvalue %2#1[0] : !llvm.struct<(i32)> +/// %tuple = tuple.from_elements %3 : tuple static llvm::SmallVector buildNextBody(ConstantStreamOp op, OpBuilder &builder, Value initialState, ArrayRef upstreamInfos, Type elementType) { @@ -430,6 +432,8 @@ buildNextBody(ConstantStreamOp op, OpBuilder &builder, Value initialState, MLIRContext *context = builder.getContext(); Type i32 = b.getI32Type(); Type opaquePtrType = LLVMPointerType::get(context); + auto tupleType = elementType.cast(); + auto structType = LLVMStructType::getLiteral(context, tupleType.getTypes()); // Extract current index. Value currentIndex = b.create( @@ -456,26 +460,34 @@ buildNextBody(ConstantStreamOp op, OpBuilder &builder, Value initialState, initialState, b.getIndexAttr(0), updatedCurrentIndex); // Load element from global data at current index. - GlobalOp globalArray = buildGlobalData(op, b, elementType); + GlobalOp globalArray = buildGlobalData(op, b, structType); Value globalPtr = b.create(opaquePtrType, globalArray.getName()); - Value gep = b.create(opaquePtrType, elementType, globalPtr, + Value gep = b.create(opaquePtrType, structType, globalPtr, ArrayRef{currentIndex, 0}); - Value nextElement = b.create(elementType, gep); + Value nextStruct = b.create(structType, gep); - b.create(ValueRange{updatedState, nextElement}); + b.create(ValueRange{updatedState, nextStruct}); }, /*elseBuilder=*/ [&](OpBuilder &builder, Location loc) { ImplicitLocOpBuilder b(loc, builder); // Don't modify state; return undef element. - Value nextElement = b.create(elementType); - b.create(ValueRange{initialState, nextElement}); + Value nextStruct = b.create(structType); + b.create(ValueRange{initialState, nextStruct}); }); + // Convert LLVM struct to tuple. + Value nextStruct = ifOp.getResult(1); + SmallVector elements; + for (auto [i, fieldType] : llvm::enumerate(structType.getBody())) { + auto element = b.create(fieldType, nextStruct, i); + elements.push_back(element); + } + Value nextElement = b.create(elementType, elements); + Value finalState = ifOp->getResult(0); - Value nextElement = ifOp.getResult(1); return {finalState, hasNext, nextElement}; } @@ -781,8 +793,22 @@ buildNextBody(MapOp op, OpBuilder &builder, Value initialState, [&](OpBuilder &builder, Location loc) { // Return undefined value. ImplicitLocOpBuilder b(loc, builder); - Value undef = b.create(elementType); - b.create(undef); + // TODO(ingomueller): Find a more extensible design. + Value defaultElement; + if (auto tupleType = elementType.dyn_cast()) { + // Special case for tuples: hope that field types are undef'able. + SmallVector fieldValues; + for (Type fieldType : tupleType.getTypes()) { + auto fieldValue = b.create(fieldType); + fieldValues.push_back(fieldValue); + } + defaultElement = + b.create(tupleType, fieldValues); + } else { + // Default case: hope that type is undef'able. + defaultElement = b.create(elementType); + } + b.create(defaultElement); }); Value mappedElement = ifOp.getResult(0); diff --git a/experimental/iterators/test/Conversion/IteratorsToLLVM/constant-stream.mlir b/experimental/iterators/test/Conversion/IteratorsToLLVM/constant-stream.mlir index d480b0ff1441..777d241b2d1f 100644 --- a/experimental/iterators/test/Conversion/IteratorsToLLVM/constant-stream.mlir +++ b/experimental/iterators/test/Conversion/IteratorsToLLVM/constant-stream.mlir @@ -1,8 +1,6 @@ // RUN: iterators-opt %s -convert-iterators-to-llvm \ // RUN: | FileCheck --enable-var-scope %s -!element_type = !llvm.struct<(i32)> - // CHECK-LABEL: func private @iterators.constantstream.close.{{[0-9]+}}(%{{.*}}: !iterators.state) -> !iterators.state // CHECK-NEXT: return %[[arg0:.*]] : !iterators.state // CHECK-NEXT: } @@ -28,7 +26,7 @@ // CHECK-NEXT: llvm.return %[[V16]] : !llvm.array<4 x struct<(i32)>> // CHECK-NEXT: } -// CHECK-LABEL: func private @iterators.constantstream.next.{{[0-9]+}}(%{{.*}}: !iterators.state) -> (!iterators.state, i1, !llvm.struct<(i32)>) +// CHECK-LABEL: func private @iterators.constantstream.next.{{[0-9]+}}(%{{.*}}: !iterators.state) -> (!iterators.state, i1, tuple) // CHECK-NEXT: %[[V0:.*]] = iterators.extractvalue %[[arg0:.*]][0] : !iterators.state // CHECK-NEXT: %[[V1:.*]] = arith.constant 4 : i32 // CHECK-NEXT: %[[V2:.*]] = arith.cmpi slt, %[[V0]], %[[V1]] : i32 @@ -44,7 +42,9 @@ // CHECK-NEXT: %[[Vb:.*]] = llvm.mlir.undef : !llvm.struct<(i32)> // CHECK-NEXT: scf.yield %[[arg0]], %[[Vb]] : !iterators.state, !llvm.struct<(i32)> // CHECK-NEXT: } -// CHECK-NEXT: return %[[V3]]#0, %[[V2]], %[[V3]]#1 : !iterators.state, i1, !llvm.struct<(i32)> +// CHECK-NEXT: %[[Vc:.*]] = llvm.extractvalue %[[V3]]#1[0] : !llvm.struct<(i32)> +// CHECK-NEXT: %[[Vd:.*]] = tuple.from_elements %[[Vc]] : tuple +// CHECK-NEXT: return %[[V3]]#0, %[[V2]], %[[Vd]] : !iterators.state, i1, tuple // CHECK-NEXT: } // CHECK-LABEL: func private @iterators.constantstream.open.{{[0-9]+}}(%{{.*}}: !iterators.state) -> !iterators.state @@ -57,7 +57,7 @@ func.func @main() { // CHECK-LABEL: func.func @main() %input = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32], [3 : i32]] } - : () -> (!iterators.stream) + : () -> (!iterators.stream>) // CHECK-NEXT: %[[V0:.*]] = arith.constant 0 : i32 // CHECK-NEXT: %[[V1:.*]] = iterators.createstate(%[[V0]]) : !iterators.state return diff --git a/experimental/iterators/test/Conversion/IteratorsToLLVM/filter.mlir b/experimental/iterators/test/Conversion/IteratorsToLLVM/filter.mlir index a397a629f0c9..4d58eac53a81 100644 --- a/experimental/iterators/test/Conversion/IteratorsToLLVM/filter.mlir +++ b/experimental/iterators/test/Conversion/IteratorsToLLVM/filter.mlir @@ -1,8 +1,6 @@ // RUN: iterators-opt %s -convert-iterators-to-llvm \ // RUN: | FileCheck --enable-var-scope %s -!element_type = !llvm.struct<(i32)> - // CHECK-LABEL: func.func private @iterators.filter.close.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> !iterators.state> { // CHECK-NEXT: %[[V0:.*]] = iterators.extractvalue %[[arg0:.*]][0] : !iterators.state> // CHECK-NEXT: %[[V1:.*]] = call @iterators.{{[a-zA-Z]+}}.close.{{[0-9]+}}(%[[V0]]) : ([[upstreamStateType:.*]]) -> [[upstreamStateType]] @@ -10,12 +8,12 @@ // CHECK-NEXT: return %[[V2]] : !iterators.state> // CHECK-NEXT: } -// CHECK-LABEL: func.func private @iterators.filter.next.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> (!iterators.state>, i1, !llvm.struct<(i32)>) +// CHECK-LABEL: func.func private @iterators.filter.next.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> (!iterators.state>, i1, tuple) // CHECK-NEXT: %[[V0:.*]] = iterators.extractvalue %[[arg0:.*]][0] : !iterators.state> -// CHECK-NEXT: %[[V1:.*]]:3 = scf.while (%[[arg1:.*]] = %[[V0]]) : ([[upstreamStateType:.*]]) -> ([[upstreamStateType]], i1, !llvm.struct<(i32)>) { -// CHECK-NEXT: %[[V3:.*]]:3 = func.call @iterators.{{[a-zA-Z]+}}.next.0(%[[arg1]]) : ([[upstreamStateType]]) -> ([[upstreamStateType]], i1, !llvm.struct<(i32)>) +// CHECK-NEXT: %[[V1:.*]]:3 = scf.while (%[[arg1:.*]] = %[[V0]]) : ([[upstreamStateType:.*]]) -> ([[upstreamStateType]], i1, tuple) { +// CHECK-NEXT: %[[V3:.*]]:3 = func.call @iterators.{{[a-zA-Z]+}}.next.0(%[[arg1]]) : ([[upstreamStateType]]) -> ([[upstreamStateType]], i1, tuple) // CHECK-NEXT: %[[V4:.*]] = scf.if %[[V3]]#1 -> (i1) { -// CHECK-NEXT: %[[V7:.*]] = func.call @is_positive_struct(%[[V3]]#2) : (!llvm.struct<(i32)>) -> i1 +// CHECK-NEXT: %[[V7:.*]] = func.call @is_positive_tuple(%[[V3]]#2) : (tuple) -> i1 // CHECK-NEXT: scf.yield %[[V7]] : i1 // CHECK-NEXT: } else { // CHECK-NEXT: scf.yield %[[V3]]#1 : i1 @@ -23,13 +21,13 @@ // CHECK-NEXT: %[[Vtrue:.*]] = arith.constant true // CHECK-NEXT: %[[V5:.*]] = arith.xori %[[V4]], %[[Vtrue]] : i1 // CHECK-NEXT: %[[V6:.*]] = arith.andi %[[V3]]#1, %[[V5]] : i1 -// CHECK-NEXT: scf.condition(%[[V6]]) %[[V3]]#0, %[[V3]]#1, %[[V3]]#2 : [[upstreamStateType]], i1, !llvm.struct<(i32)> +// CHECK-NEXT: scf.condition(%[[V6]]) %[[V3]]#0, %[[V3]]#1, %[[V3]]#2 : [[upstreamStateType]], i1, tuple // CHECK-NEXT: } do { -// CHECK-NEXT: ^bb0(%[[arg2:.*]]: [[upstreamStateType]], %arg2: i1, %arg3: !llvm.struct<(i32)>): +// CHECK-NEXT: ^bb0(%[[arg2:.*]]: [[upstreamStateType]], %arg2: i1, %arg3: tuple): // CHECK-NEXT: scf.yield %[[arg2]] : [[upstreamStateType]] // CHECK-NEXT: } // CHECK-NEXT: %[[V2:.*]] = iterators.insertvalue %[[V1]]#0 into %[[arg0]][0] : !iterators.state> -// CHECK-NEXT: return %[[V2]], %[[V1]]#1, %[[V1]]#2 : !iterators.state>, i1, !llvm.struct<(i32)> +// CHECK-NEXT: return %[[V2]], %[[V1]]#1, %[[V1]]#2 : !iterators.state>, i1, tuple // CHECK-NEXT: } // CHECK-LABEL: func.func private @iterators.filter.open.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> !iterators.state> @@ -39,25 +37,25 @@ // CHECK-NEXT: return %[[V2]] : !iterators.state> // CHECK-NEXT: } -func.func private @is_positive_struct(%struct : !element_type) -> i1 { -// CHECK-LABEL: func.func private @is_positive_struct(%{{.*}}: !llvm.struct<(i32)>) -> i1 { - %i = llvm.extractvalue %struct[0] : !element_type -// CHECK-NEXT: %[[i:.*]] = llvm.extractvalue %[[struct:.*]][0] : !llvm.struct<(i32)> +// CHECK-LABEL: func.func private @is_positive_tuple( +// CHECK-SAME: %[[ARG0:.*]]: tuple) -> i1 { +// CHECK-DAG: %[[V0:.*]] = tuple.to_elements %[[ARG0]] : tuple +// CHECK-DAG: %[[V1:.*]] = arith.constant 0 : i32 +// CHECK-NEXT: %[[V2:.*]] = arith.cmpi sgt, %[[V0]], %[[V1]] : i32 +// CHECK-NEXT: return %[[V2]] : i1 +func.func private @is_positive_tuple(%tuple : tuple) -> i1 { + %i = tuple.to_elements %tuple : tuple %zero = arith.constant 0 : i32 -// CHECK-NEXT: %[[zero:.*]] = arith.constant 0 : i32 %cmp = arith.cmpi "sgt", %i, %zero : i32 -// CHECK-NEXT: %[[cmp:.*]] = arith.cmpi sgt, %[[i]], %[[zero]] : i32 return %cmp : i1 -// CHECK-NEXT: return %[[cmp]] : i1 } -// CHECK-NEXT: } func.func @main() { // CHECK-LABEL: func.func @main() - %input = "iterators.constantstream"() { value = [] } : () -> (!iterators.stream) + %input = "iterators.constantstream"() { value = [] } : () -> (!iterators.stream>) // CHECK: %[[V0:.*]] = iterators.createstate({{.*}}) : [[upstreamStateType:.*]] - %filter = "iterators.filter"(%input) {predicateRef = @is_positive_struct} - : (!iterators.stream) -> (!iterators.stream) + %filter = "iterators.filter"(%input) {predicateRef = @is_positive_tuple} + : (!iterators.stream>) -> (!iterators.stream>) // CHECK-NEXT: %[[V1:.*]] = iterators.createstate(%[[V0]]) : !iterators.state<[[upstreamStateType]]> return // CHECK-NEXT: return diff --git a/experimental/iterators/test/Conversion/IteratorsToLLVM/map.mlir b/experimental/iterators/test/Conversion/IteratorsToLLVM/map.mlir index 403a9a38384f..d3f0e5c4cd4d 100644 --- a/experimental/iterators/test/Conversion/IteratorsToLLVM/map.mlir +++ b/experimental/iterators/test/Conversion/IteratorsToLLVM/map.mlir @@ -1,8 +1,6 @@ // RUN: iterators-opt %s -convert-iterators-to-llvm \ // RUN: | FileCheck --enable-var-scope %s -!element_type = !llvm.struct<(i32)> - // CHECK-LABEL: func.func private @iterators.map.close.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> !iterators.state> { // CHECK-NEXT: %[[V0:.*]] = iterators.extractvalue %[[arg0:.*]][0] : !iterators.state> // CHECK-NEXT: %[[V1:.*]] = call @iterators.{{[a-zA-Z]+}}.close.{{[0-9]+}}(%[[V0]]) : (!iterators.state) -> !iterators.state @@ -10,18 +8,19 @@ // CHECK-NEXT: return %[[V2]] : !iterators.state> // CHECK-NEXT: } -// CHECK-LABEL: func.func private @iterators.map.next.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> (!iterators.state>, i1, !llvm.struct<(i32)>) +// CHECK-LABEL: func.func private @iterators.map.next.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> (!iterators.state>, i1, tuple) // CHECK-NEXT: %[[V0:.*]] = iterators.extractvalue %[[arg0:.*]][0] : !iterators.state> -// CHECK-NEXT: %[[V1:.*]]:3 = call @iterators.{{[a-zA-Z]+}}.next.0(%[[V0]]) : (!iterators.state) -> (!iterators.state, i1, !llvm.struct<(i32)>) -// CHECK-NEXT: %[[V2:.*]] = scf.if %[[V1]]#1 -> (!llvm.struct<(i32)>) { -// CHECK-NEXT: %[[V4:.*]] = func.call @double_struct(%[[V1]]#2) : (!llvm.struct<(i32)>) -> !llvm.struct<(i32)> -// CHECK-NEXT: scf.yield %[[V4]] : !llvm.struct<(i32)> +// CHECK-NEXT: %[[V1:.*]]:3 = call @iterators.{{[a-zA-Z]+}}.next.0(%[[V0]]) : (!iterators.state) -> (!iterators.state, i1, tuple) +// CHECK-NEXT: %[[V2:.*]] = scf.if %[[V1]]#1 -> (tuple) { +// CHECK-NEXT: %[[V4:.*]] = func.call @double_tuple(%[[V1]]#2) : (tuple) -> tuple +// CHECK-NEXT: scf.yield %[[V4]] : tuple // CHECK-NEXT: } else { -// CHECK-NEXT: %[[V4]] = llvm.mlir.undef : !llvm.struct<(i32)> -// CHECK-NEXT: scf.yield %[[V4]] : !llvm.struct<(i32)> +// CHECK-NEXT: %[[V5:.*]] = llvm.mlir.undef : i32 +// CHECK-NEXT: %[[V6:.*]] = tuple.from_elements %[[V5]] : tuple +// CHECK-NEXT: scf.yield %[[V6]] : tuple // CHECK-NEXT: } // CHECK-NEXT: %[[V3:.*]] = iterators.insertvalue %[[V1]]#0 into %arg0[0] : !iterators.state> -// CHECK-NEXT: return %[[V3]], %[[V1]]#1, %[[V2]] : !iterators.state>, i1, !llvm.struct<(i32)> +// CHECK-NEXT: return %[[V3]], %[[V1]]#1, %[[V2]] : !iterators.state>, i1, tuple // CHECK-NEXT: } // CHECK-LABEL: func.func private @iterators.map.open.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> !iterators.state> @@ -31,27 +30,26 @@ // CHECK-NEXT: return %[[V2]] : !iterators.state> // CHECK-NEXT: } -func.func private @double_struct(%struct : !element_type) -> !element_type { -// CHECK-LABEL: func.func private @double_struct(%{{.*}}: !llvm.struct<(i32)>) -> !llvm.struct<(i32)> { - %i = llvm.extractvalue %struct[0] : !element_type -// CHECK-NEXT: %[[V0:.*]] = llvm.extractvalue %[[arg0:.*]][0] : !llvm.struct<(i32)> - %doubled = arith.addi %i, %i : i32 +// CHECK-LABEL: func.func private @double_tuple(%{{.*}}: tuple) -> tuple { +// CHECK-NEXT: %[[V0:.*]] = tuple.to_elements %[[arg0:.*]] : tuple // CHECK-NEXT: %[[V1:.*]] = arith.addi %[[V0]], %[[V0]] : i32 - %result = llvm.insertvalue %doubled, %struct[0] : !element_type -// CHECK-NEXT: %[[V2:.*]] = llvm.insertvalue %[[V1]], %[[arg0]][0] : !llvm.struct<(i32)> - return %result : !element_type -// CHECK-NEXT: return %[[V2]] : !llvm.struct<(i32)> +// CHECK-NEXT: %[[V2:.*]] = tuple.from_elements %[[V1]] : tuple +// CHECK-NEXT: return %[[V2]] : tuple +func.func private @double_tuple(%tuple : tuple) -> tuple { + %i = tuple.to_elements %tuple : tuple + %doubled = arith.addi %i, %i : i32 + %result = tuple.from_elements %doubled : tuple + return %result : tuple } -// CHECK-NEXT: } func.func @main() { // CHECK-LABEL: func.func @main() { %input = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32], [3 : i32]] } - : () -> (!iterators.stream) + : () -> (!iterators.stream>) // CHECK: %[[V0:.*]] = iterators.createstate({{.*}}) : [[upstreamStateType:.*]] - %reduce = "iterators.map"(%input) {mapFuncRef = @double_struct} - : (!iterators.stream) -> (!iterators.stream) + %reduce = "iterators.map"(%input) {mapFuncRef = @double_tuple} + : (!iterators.stream>) -> (!iterators.stream>) // CHECK-NEXT: %[[V1:.*]] = iterators.createstate(%[[V0]]) : !iterators.state<[[upstreamStateType]]> return // CHECK-NEXT: return diff --git a/experimental/iterators/test/Conversion/IteratorsToLLVM/reduce.mlir b/experimental/iterators/test/Conversion/IteratorsToLLVM/reduce.mlir index a7e5da352811..4031d67de46f 100644 --- a/experimental/iterators/test/Conversion/IteratorsToLLVM/reduce.mlir +++ b/experimental/iterators/test/Conversion/IteratorsToLLVM/reduce.mlir @@ -1,8 +1,6 @@ // RUN: iterators-opt %s -convert-iterators-to-llvm \ // RUN: | FileCheck --enable-var-scope %s -!element_type = !llvm.struct<(i32)> - // CHECK-LABEL: func private @iterators.reduce.close.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> !iterators.state> { // CHECK-NEXT: %[[V0:.*]] = iterators.extractvalue %[[arg0:.*]][0] : !iterators.state> // CHECK-NEXT: %[[V1:.*]] = call @iterators.{{[a-zA-Z]+}}.close.{{[0-9]+}}(%[[V0]]) : (!iterators.state) -> !iterators.state @@ -10,25 +8,25 @@ // CHECK-NEXT: return %[[V2]] : !iterators.state> // CHECK-NEXT: } -// CHECK-LABEL: func private @iterators.reduce.next.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> (!iterators.state>, i1, !llvm.struct<(i32)>) +// CHECK-LABEL: func private @iterators.reduce.next.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> (!iterators.state>, i1, tuple) // CHECK-NEXT: %[[V0:.*]] = iterators.extractvalue %[[arg0:.*]][0] : !iterators.state> -// CHECK-NEXT: %[[V1:.*]]:3 = call @iterators.{{[a-zA-Z]+}}.next.{{[0-9]+}}(%[[V0]]) : (!iterators.state) -> (!iterators.state, i1, !llvm.struct<(i32)>) -// CHECK-NEXT: %[[V2:.*]]:3 = scf.if %[[V1]]#1 -> (!iterators.state, i1, !llvm.struct<(i32)>) { -// CHECK-NEXT: %[[V4:.*]]:3 = scf.while (%[[arg1:.*]] = %[[V1]]#0, %[[arg2:.*]] = %[[V1]]#2) : (!iterators.state, !llvm.struct<(i32)>) -> (!iterators.state, !llvm.struct<(i32)>, !llvm.struct<(i32)>) { -// CHECK-NEXT: %[[V5:.*]]:3 = func.call @iterators.{{[a-zA-Z]+}}.next.{{[0-9]+}}(%[[arg1]]) : (!iterators.state) -> (!iterators.state, i1, !llvm.struct<(i32)>) -// CHECK-NEXT: scf.condition(%[[V5]]#1) %[[V5]]#0, %[[arg2]], %[[V5]]#2 : !iterators.state, !llvm.struct<(i32)>, !llvm.struct<(i32)> +// CHECK-NEXT: %[[V1:.*]]:3 = call @iterators.{{[a-zA-Z]+}}.next.{{[0-9]+}}(%[[V0]]) : (!iterators.state) -> (!iterators.state, i1, tuple) +// CHECK-NEXT: %[[V2:.*]]:3 = scf.if %[[V1]]#1 -> (!iterators.state, i1, tuple) { +// CHECK-NEXT: %[[V4:.*]]:3 = scf.while (%[[arg1:.*]] = %[[V1]]#0, %[[arg2:.*]] = %[[V1]]#2) : (!iterators.state, tuple) -> (!iterators.state, tuple, tuple) { +// CHECK-NEXT: %[[V5:.*]]:3 = func.call @iterators.{{[a-zA-Z]+}}.next.{{[0-9]+}}(%[[arg1]]) : (!iterators.state) -> (!iterators.state, i1, tuple) +// CHECK-NEXT: scf.condition(%[[V5]]#1) %[[V5]]#0, %[[arg2]], %[[V5]]#2 : !iterators.state, tuple, tuple // CHECK-NEXT: } do { -// CHECK-NEXT: ^[[bb0:.*]](%[[arg1:.*]]: !iterators.state, %[[arg2:.*]]: !llvm.struct<(i32)>, %[[arg3:.*]]: !llvm.struct<(i32)>): -// CHECK-NEXT: %[[V5:.*]] = func.call @sum_struct(%[[arg2]], %[[arg3]]) : (!llvm.struct<(i32)>, !llvm.struct<(i32)>) -> !llvm.struct<(i32)> -// CHECK-NEXT: scf.yield %[[arg1]], %[[V5]] : !iterators.state, !llvm.struct<(i32)> +// CHECK-NEXT: ^[[bb0:.*]](%[[arg1:.*]]: !iterators.state, %[[arg2:.*]]: tuple, %[[arg3:.*]]: tuple): +// CHECK-NEXT: %[[V5:.*]] = func.call @sum_tuple(%[[arg2]], %[[arg3]]) : (tuple, tuple) -> tuple +// CHECK-NEXT: scf.yield %[[arg1]], %[[V5]] : !iterators.state, tuple // CHECK-NEXT: } // CHECK-NEXT: %[[true:.*]] = arith.constant true -// CHECK-NEXT: scf.yield %[[V4]]#0, %[[true]], %[[V4]]#1 : !iterators.state, i1, !llvm.struct<(i32)> +// CHECK-NEXT: scf.yield %[[V4]]#0, %[[true]], %[[V4]]#1 : !iterators.state, i1, tuple // CHECK-NEXT: } else { -// CHECK-NEXT: scf.yield %[[V1]]#0, %[[V1]]#1, %[[V1]]#2 : !iterators.state, i1, !llvm.struct<(i32)> +// CHECK-NEXT: scf.yield %[[V1]]#0, %[[V1]]#1, %[[V1]]#2 : !iterators.state, i1, tuple // CHECK-NEXT: } // CHECK-NEXT: %[[V3:.*]] = iterators.insertvalue %[[V2]]#0 into %[[arg0]][0] : !iterators.state> -// CHECK-NEXT: return %[[V3]], %[[V2]]#1, %[[V2]]#2 : !iterators.state>, i1, !llvm.struct<(i32)> +// CHECK-NEXT: return %[[V3]], %[[V2]]#1, %[[V2]]#2 : !iterators.state>, i1, tuple // CHECK-NEXT: } // CHECK-LABEL: func private @iterators.reduce.open.{{[0-9]+}}(%{{.*}}: !iterators.state>) -> !iterators.state> @@ -38,27 +36,28 @@ // CHECK-NEXT: return %[[V2]] : !iterators.state> // CHECK-NEXT: } -func.func private @sum_struct(%lhs : !element_type, %rhs : !element_type) -> !element_type { -// CHECK-LABEL: func private @sum_struct(%{{.*}}: !llvm.struct<(i32)>, %{{.*}}: !llvm.struct<(i32)>) -> !llvm.struct<(i32)> - %lhsi = llvm.extractvalue %lhs[0] : !element_type -// CHECK-NEXT: %[[lhsi:.*]] = llvm.extractvalue %[[lhs:.*]][0] : !llvm.struct<(i32)> - %rhsi = llvm.extractvalue %rhs[0] : !element_type -// CHECK-NEXT: %[[rhsi:.*]] = llvm.extractvalue %[[rhs:.*]][0] : !llvm.struct<(i32)> +// CHECK-LABEL: func private @sum_tuple( +// CHECK-SAME: %[[ARG0:[^:]*]]: tuple, +// CHECK-SAME: %[[ARG1:[^:]*]]: tuple) -> tuple +// CHECK-NEXT: %[[V0:.*]] = tuple.to_elements %[[ARG0]] : tuple +// CHECK-NEXT: %[[V1:.*]] = tuple.to_elements %[[ARG1]] : tuple +// CHECK-NEXT: %[[V2:.*]] = arith.addi %[[V0]], %[[V1]] : i32 +// CHECK-NEXT: %[[V3:.*]] = tuple.from_elements %[[V2]] : tuple +// CHECK-NEXT: return %[[V3]] : tuple +func.func private @sum_tuple(%lhs : tuple, %rhs : tuple) -> tuple { + %lhsi = tuple.to_elements %lhs : tuple + %rhsi = tuple.to_elements %rhs : tuple %i = arith.addi %lhsi, %rhsi : i32 -// CHECK-NEXT: %[[i:.*]] = arith.addi %[[lhsi]], %[[rhsi]] : i32 - %result = llvm.insertvalue %i, %lhs[0] : !element_type -// CHECK-NEXT: %[[result:.*]] = llvm.insertvalue %[[i]], %[[lhs]][0] : !llvm.struct<(i32)> - return %result : !element_type -// CHECK-NEXT: return %[[result]] : !llvm.struct<(i32)> + %result = tuple.from_elements %i : tuple + return %result : tuple } -// CHECK-NEXT: } func.func @main() { // CHECK-LABEL: func.func @main() - %input = "iterators.constantstream"() { value = [] } : () -> (!iterators.stream) + %input = "iterators.constantstream"() { value = [] } : () -> (!iterators.stream>) // CHECK: %[[V0:.*]] = iterators.createstate({{.*}}) : [[upstreamStateType:.*]] - %reduce = "iterators.reduce"(%input) {reduceFuncRef = @sum_struct} - : (!iterators.stream) -> (!iterators.stream) + %reduce = "iterators.reduce"(%input) {reduceFuncRef = @sum_tuple} + : (!iterators.stream>) -> (!iterators.stream>) // CHECK-NEXT: %[[V1:.*]] = iterators.createstate(%[[V0]]) : !iterators.state<[[upstreamStateType]]> return // CHECK-NEXT: return diff --git a/experimental/iterators/test/Conversion/IteratorsToLLVM/sink.mlir b/experimental/iterators/test/Conversion/IteratorsToLLVM/sink.mlir index 06e7da91426b..cf4909c1afd7 100644 --- a/experimental/iterators/test/Conversion/IteratorsToLLVM/sink.mlir +++ b/experimental/iterators/test/Conversion/IteratorsToLLVM/sink.mlir @@ -1,21 +1,19 @@ // RUN: iterators-opt %s -convert-iterators-to-llvm \ // RUN: | FileCheck --enable-var-scope %s -!element_type = !llvm.struct<(i32)> - func.func @main() { // CHECK-LABEL: func.func @main() - %input = "iterators.constantstream"() { value = [] } : () -> (!iterators.stream) - "iterators.sink"(%input) : (!iterators.stream) -> () + %input = "iterators.constantstream"() { value = [] } : () -> (!iterators.stream>) + "iterators.sink"(%input) : (!iterators.stream>) -> () // CHECK: %[[V1:.*]] = call @[[rootIteratorName:.*]].open.{{[0-9]+}}(%[[V0:.*]]) : ([[rootStateType:.*]]) -> [[rootStateType]] - // CHECK-NEXT: %[[V2:.*]]:2 = scf.while (%[[arg0:.*]] = %[[V1]]) : ([[rootStateType]]) -> ([[rootStateType]], !llvm.struct<(i32)>) { - // CHECK-NEXT: %[[V4:.*]]:3 = func.call @[[rootIteratorName]].next.{{[0-9]+}}(%[[arg0]]) : ([[rootStateType]]) -> ([[rootStateType]], i1, !llvm.struct<(i32)>) - // CHECK-NEXT: scf.condition(%[[V4]]#1) %[[V4]]#0, %[[V4]]#2 : [[rootStateType]], !llvm.struct<(i32)> + // CHECK-NEXT: %[[V2:.*]]:2 = scf.while (%[[arg0:.*]] = %[[V1]]) : ([[rootStateType]]) -> ([[rootStateType]], tuple) { + // CHECK-NEXT: %[[V4:.*]]:3 = func.call @[[rootIteratorName]].next.{{[0-9]+}}(%[[arg0]]) : ([[rootStateType]]) -> ([[rootStateType]], i1, tuple) + // CHECK-NEXT: scf.condition(%[[V4]]#1) %[[V4]]#0, %[[V4]]#2 : [[rootStateType]], tuple // CHECK-NEXT: } do { - // CHECK-NEXT: ^[[bb0:.*]](%[[arg1:.*]]: [[rootStateType]], %[[arg2:.*]]: !llvm.struct<(i32)>): + // CHECK-NEXT: ^[[bb0:.*]](%[[arg1:.*]]: [[rootStateType]], %[[arg2:.*]]: tuple): // CHECK-DAG: %[[V4:.*]] = llvm.mlir.addressof @iterators.frmt_spec{{(\.[0-9]+)?}} : !llvm.ptr // CHECK-DAG: %[[V6:.*]] = llvm.getelementptr %[[V4]][0] : (!llvm.ptr) -> !llvm.ptr, i8 - // CHECK-DAG: %[[V7:.*]] = llvm.extractvalue %[[arg2:.*]][0] : !llvm.struct<(i32)> + // CHECK-DAG: %[[V7:.*]] = tuple.to_elements %[[arg2:.*]] : tuple // CHECK-DAG: %[[V9:.*]] = arith.extui %[[V7]] : i32 to i64 // CHECK-NEXT: %[[V8:.*]] = llvm.call @printf(%[[V6]], %[[V9]]) : (!llvm.ptr, i64) -> i32 // CHECK-NEXT: scf.yield %[[arg1]] : [[rootStateType]] diff --git a/experimental/iterators/test/Dialect/Iterators/constant-stream.mlir b/experimental/iterators/test/Dialect/Iterators/constant-stream.mlir index 7b0e263665e2..77102a18ff19 100644 --- a/experimental/iterators/test/Dialect/Iterators/constant-stream.mlir +++ b/experimental/iterators/test/Dialect/Iterators/constant-stream.mlir @@ -4,17 +4,17 @@ func.func @main() { // CHECK-LABEL: func.func @main() { %empty = "iterators.constantstream"() { value = [] } : - () -> (!iterators.stream>) -// CHECK-NEXT: %[[V0:constantstream.*]] = "iterators.constantstream"() {value = []} : () -> !iterators.stream> + () -> (!iterators.stream>) +// CHECK-NEXT: %[[V0:constantstream.*]] = "iterators.constantstream"() {value = []} : () -> !iterators.stream> %i32 = "iterators.constantstream"() { value = [[42 : i32]] } : - () -> (!iterators.stream>) -// CHECK-NEXT: %[[V1:constantstream.*]] = "iterators.constantstream"() {value = {{\[}}[42 : i32]]} : () -> !iterators.stream> + () -> (!iterators.stream>) +// CHECK-NEXT: %[[V1:constantstream.*]] = "iterators.constantstream"() {value = {{\[}}[42 : i32]]} : () -> !iterators.stream> %f32 = "iterators.constantstream"() { value = [[42. : f32]] } : - () -> (!iterators.stream>) -// CHECK-NEXT: %[[V2:constantstream.*]] = "iterators.constantstream"() {value = {{\[}}[4.200000e+01 : f32]]} : () -> !iterators.stream> + () -> (!iterators.stream>) +// CHECK-NEXT: %[[V2:constantstream.*]] = "iterators.constantstream"() {value = {{\[}}[4.200000e+01 : f32]]} : () -> !iterators.stream> %i32i64 = "iterators.constantstream"() { value = [[42 : i32, 1337 : i64]] } : - () -> (!iterators.stream>) -// CHECK-NEXT: %[[V3:constantstream.*]] = "iterators.constantstream"() {value = {{\[}}[42 : i32, 1337]]} : () -> !iterators.stream> + () -> (!iterators.stream>) +// CHECK-NEXT: %[[V3:constantstream.*]] = "iterators.constantstream"() {value = {{\[}}[42 : i32, 1337]]} : () -> !iterators.stream> return // CHECK-NEXT: return } diff --git a/experimental/iterators/test/Dialect/Iterators/filter.mlir b/experimental/iterators/test/Dialect/Iterators/filter.mlir index 557ff18837d2..c9d6563e5c27 100644 --- a/experimental/iterators/test/Dialect/Iterators/filter.mlir +++ b/experimental/iterators/test/Dialect/Iterators/filter.mlir @@ -1,10 +1,9 @@ // RUN: iterators-opt %s \ // RUN: | FileCheck %s -!i32_struct = !llvm.struct<(i32)> -func.func private @is_positive_struct(%struct : !i32_struct) -> i1 { - %i = llvm.extractvalue %struct[0] : !i32_struct +func.func private @is_positive_tuple(%tuple : tuple) -> i1 { + %i = tuple.to_elements %tuple : tuple %zero = arith.constant 0 : i32 %cmp = arith.cmpi "sgt", %i, %zero : i32 return %cmp : i1 @@ -13,12 +12,12 @@ func.func private @is_positive_struct(%struct : !i32_struct) -> i1 { func.func @main() { // CHECK-LABEL: func.func @main() { %input = "iterators.constantstream"() { value = [] } : - () -> (!iterators.stream) + () -> (!iterators.stream>) // CHECK-NEXT: %[[V0:.*]] = "iterators.constantstream"{{.*}} - %filtered = "iterators.filter"(%input) {predicateRef = @is_positive_struct} : - (!iterators.stream) -> - (!iterators.stream) -// CHECK-NEXT: %[[V1:filtered.*]] = "iterators.filter"(%[[V0]]) {predicateRef = @is_positive_struct} : (!iterators.stream>) -> !iterators.stream> + %filtered = "iterators.filter"(%input) {predicateRef = @is_positive_tuple} : + (!iterators.stream>) -> + (!iterators.stream>) +// CHECK-NEXT: %[[V1:filtered.*]] = "iterators.filter"(%[[V0]]) {predicateRef = @is_positive_tuple} : (!iterators.stream>) -> !iterators.stream> return // CHECK-NEXT: return } diff --git a/experimental/iterators/test/Dialect/Iterators/map.mlir b/experimental/iterators/test/Dialect/Iterators/map.mlir index 42630b77baa9..32d4ab7e7015 100644 --- a/experimental/iterators/test/Dialect/Iterators/map.mlir +++ b/experimental/iterators/test/Dialect/Iterators/map.mlir @@ -1,21 +1,19 @@ // RUN: iterators-opt %s \ // RUN: | FileCheck %s -!i32_struct = !llvm.struct<(i32)> - -func.func private @unpack_i32(%input : !i32_struct) -> i32 { - %i = llvm.extractvalue %input[0] : !i32_struct +func.func private @unpack_i32(%input : tuple) -> i32 { + %i = tuple.to_elements %input : tuple return %i : i32 } func.func @main() { // CHECK-LABEL: func.func @main() { %input = "iterators.constantstream"() { value = [] } : - () -> (!iterators.stream) + () -> (!iterators.stream>) // CHECK-NEXT: %[[V0:.*]] = "iterators.constantstream"{{.*}} %unpacked = "iterators.map"(%input) {mapFuncRef = @unpack_i32} : - (!iterators.stream) -> (!iterators.stream) -// CHECK-NEXT: %[[V1:mapped.*]] = "iterators.map"(%[[V0]]) {mapFuncRef = @unpack_i32} : (!iterators.stream>) -> !iterators.stream + (!iterators.stream>) -> (!iterators.stream) +// CHECK-NEXT: %[[V1:mapped.*]] = "iterators.map"(%[[V0]]) {mapFuncRef = @unpack_i32} : (!iterators.stream>) -> !iterators.stream return // CHECK-NEXT: return } diff --git a/experimental/iterators/test/Dialect/Iterators/reduce.mlir b/experimental/iterators/test/Dialect/Iterators/reduce.mlir index 06a4ee3851a3..a6fd7037b0bc 100644 --- a/experimental/iterators/test/Dialect/Iterators/reduce.mlir +++ b/experimental/iterators/test/Dialect/Iterators/reduce.mlir @@ -1,25 +1,23 @@ // RUN: iterators-opt %s \ // RUN: | FileCheck %s -!i32_struct = !llvm.struct<(i32)> - -func.func private @sum_struct(%lhs : !i32_struct, %rhs : !i32_struct) -> !i32_struct { - %lhsi = llvm.extractvalue %lhs[0] : !i32_struct - %rhsi = llvm.extractvalue %rhs[0] : !i32_struct +func.func private @sum_tuple(%lhs : tuple, %rhs : tuple) -> tuple { + %lhsi = tuple.to_elements %lhs : tuple + %rhsi = tuple.to_elements %rhs : tuple %i = arith.addi %lhsi, %rhsi : i32 - %result = llvm.insertvalue %i, %lhs[0] : !i32_struct - return %result : !i32_struct + %result = tuple.from_elements %i : tuple + return %result : tuple } func.func @main() { // CHECK-LABEL: func.func @main() { %input = "iterators.constantstream"() { value = [] } : - () -> (!iterators.stream) + () -> (!iterators.stream>) // CHECK-NEXT: %[[V0:.*]] = "iterators.constantstream"{{.*}} - %reduced = "iterators.reduce"(%input) {reduceFuncRef = @sum_struct} : - (!iterators.stream) -> - (!iterators.stream) -// CHECK-NEXT: %[[V1:reduced.*]] = "iterators.reduce"(%[[V0]]) {reduceFuncRef = @sum_struct} : (!iterators.stream>) -> !iterators.stream> + %reduced = "iterators.reduce"(%input) {reduceFuncRef = @sum_tuple} : + (!iterators.stream>) -> + (!iterators.stream>) +// CHECK-NEXT: %[[V1:reduced.*]] = "iterators.reduce"(%[[V0]]) {reduceFuncRef = @sum_tuple} : (!iterators.stream>) -> !iterators.stream> return // CHECK-NEXT: return } diff --git a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/constant-stream.mlir b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/constant-stream.mlir index e12855406e9b..a2730a4b7300 100644 --- a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/constant-stream.mlir +++ b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/constant-stream.mlir @@ -1,6 +1,7 @@ // RUN: iterators-opt %s \ // RUN: -convert-iterators-to-llvm \ // RUN: -decompose-iterator-states -canonicalize \ +// RUN: -decompose-tuples \ // RUN: -convert-func-to-llvm \ // RUN: -convert-scf-to-cf -convert-cf-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ @@ -10,8 +11,8 @@ func.func @main() { iterators.print ("zero_to_three") %zero_to_three = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32], [3 : i32]] } - : () -> (!iterators.stream>) - "iterators.sink"(%zero_to_three) : (!iterators.stream>) -> () + : () -> (!iterators.stream>) + "iterators.sink"(%zero_to_three) : (!iterators.stream>) -> () // CHECK-LABEL: zero_to_three // CHECK-NEXT: (0) // CHECK-NEXT: (1) @@ -19,18 +20,19 @@ func.func @main() { // CHECK-NEXT: (3) // CHECK-NEXT: - + iterators.print ("empty") %empty = "iterators.constantstream"() { value = [] } - : () -> (!iterators.stream>) - "iterators.sink"(%empty) : (!iterators.stream>) -> () + : () -> (!iterators.stream>) + "iterators.sink"(%empty) : (!iterators.stream>) -> () // CHECK-LABEL: empty // CHECK-NEXT: - iterators.print ("mixed_types") %mixed_types = "iterators.constantstream"() { value = [[1 : i1, 2 : i8, 3 : i16, 4 : i32, 5 : i64, 8.5 : f16, 8.25 : f32, 8.125 : f64]] } - : () -> (!iterators.stream>) - "iterators.sink"(%mixed_types) : (!iterators.stream>) -> () + : () -> (!iterators.stream>) + "iterators.sink"(%mixed_types) : (!iterators.stream>) -> () // CHECK-LABEL: mixed_types // CHECK-NEXT: (1, 2, 3, 4, 5, 8.5, 8.25, 8.125) // CHECK-NEXT: - diff --git a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/filter.mlir b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/filter.mlir index 6ac32b5bd5f3..6f3b2278e478 100644 --- a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/filter.mlir +++ b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/filter.mlir @@ -1,29 +1,28 @@ // RUN: iterators-opt %s \ // RUN: -convert-iterators-to-llvm \ // RUN: -decompose-iterator-states -canonicalize \ +// RUN: -decompose-tuples \ // RUN: -convert-func-to-llvm \ // RUN: -convert-scf-to-cf -convert-cf-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ // RUN: | FileCheck %s -!i32_struct = !llvm.struct<(i32)> - -func.func private @is_positive_struct(%struct : !i32_struct) -> i1 { - %i = llvm.extractvalue %struct[0] : !i32_struct +func.func private @is_positive_tuple(%tuple : tuple) -> i1 { + %i = tuple.to_elements %tuple : tuple %zero = arith.constant 0 : i32 %cmp = arith.cmpi "sgt", %i, %zero : i32 return %cmp : i1 } -func.func @filter_is_positive_struct() { - iterators.print ("filter_is_positive_struct") +func.func @filter_is_positive_tuple() { + iterators.print ("filter_is_positive_tuple") %input = "iterators.constantstream"() { value = [[0: i32], [1: i32], [-1: i32], [2: i32], [-2: i32]] } - : () -> (!iterators.stream) - %filtered = "iterators.filter"(%input) {predicateRef = @is_positive_struct} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%filtered) : (!iterators.stream) -> () - // CHECK-LABEL: filter_is_positive_struct + : () -> (!iterators.stream>) + %filtered = "iterators.filter"(%input) {predicateRef = @is_positive_tuple} + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%filtered) : (!iterators.stream>) -> () + // CHECK-LABEL: filter_is_positive_tuple // CHECK-NEXT: (1) // CHECK-NEXT: (2) // CHECK-NEXT: - @@ -36,8 +35,8 @@ func.func private @is_positive_i32(%i : i32) -> i1 { return %cmp : i1 } -func.func private @unpack_i32(%input : !i32_struct) -> i32 { - %i = llvm.extractvalue %input[0] : !i32_struct +func.func private @unpack_i32(%input : tuple) -> i32 { + %i = tuple.to_elements %input : tuple return %i : i32 } @@ -45,9 +44,9 @@ func.func @filter_is_positive_i32() { iterators.print ("filter_is_positive_i32") %input = "iterators.constantstream"() { value = [[0: i32], [2: i32], [-2: i32], [4: i32], [-4: i32]] } - : () -> (!iterators.stream) + : () -> (!iterators.stream>) %unpacked = "iterators.map"(%input) {mapFuncRef = @unpack_i32} - : (!iterators.stream) -> (!iterators.stream) + : (!iterators.stream>) -> (!iterators.stream) %filtered = "iterators.filter"(%unpacked) {predicateRef = @is_positive_i32} : (!iterators.stream) -> (!iterators.stream) "iterators.sink"(%filtered) : (!iterators.stream) -> () @@ -59,7 +58,7 @@ func.func @filter_is_positive_i32() { } func.func @main() { - call @filter_is_positive_struct() : () -> () + call @filter_is_positive_tuple() : () -> () call @filter_is_positive_i32() : () -> () return } diff --git a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/map.mlir b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/map.mlir index 319892e39432..3b9fc06b17e9 100644 --- a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/map.mlir +++ b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/map.mlir @@ -1,29 +1,28 @@ // RUN: iterators-opt %s \ // RUN: -convert-iterators-to-llvm \ // RUN: -decompose-iterator-states -canonicalize \ +// RUN: -decompose-tuples \ // RUN: -convert-func-to-llvm \ // RUN: -convert-scf-to-cf -convert-cf-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ // RUN: | FileCheck %s -!i32_struct = !llvm.struct<(i32)> - -func.func private @double_struct(%struct : !i32_struct) -> !i32_struct { - %i = llvm.extractvalue %struct[0] : !i32_struct +func.func private @double_tuple(%tuple : tuple) -> tuple { + %i = tuple.to_elements %tuple : tuple %doubled = arith.addi %i, %i : i32 - %result = llvm.insertvalue %doubled, %struct[0] : !i32_struct - return %result : !i32_struct + %result = tuple.from_elements %doubled : tuple + return %result : tuple } -func.func @map_double_struct() { - iterators.print ("map_double_struct") +func.func @map_double_tuple() { + iterators.print ("map_double_tuple") %input = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32], [3 : i32]] } - : () -> (!iterators.stream) - %reduce = "iterators.map"(%input) {mapFuncRef = @double_struct} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%reduce) : (!iterators.stream) -> () - // CHECK-LABEL: map_double_struct + : () -> (!iterators.stream>) + %reduce = "iterators.map"(%input) {mapFuncRef = @double_tuple} + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%reduce) : (!iterators.stream>) -> () + // CHECK-LABEL: map_double_tuple // CHECK-NEXT: (0) // CHECK-NEXT: (2) // CHECK-NEXT: (4) @@ -32,25 +31,21 @@ func.func @map_double_struct() { return } -!i32f32_struct = !llvm.struct<(i32, f32)> - -func.func private @add_field(%input : !i32_struct) -> !i32f32_struct { - %i = llvm.extractvalue %input[0] : !i32_struct +func.func private @add_field(%input : tuple) -> tuple { + %i = tuple.to_elements %input : tuple %f = arith.sitofp %i : i32 to f32 - %undef = llvm.mlir.undef : !i32f32_struct - %extended = llvm.insertvalue %i, %undef[0] : !i32f32_struct - %result = llvm.insertvalue %f, %extended[1] : !i32f32_struct - return %result : !i32f32_struct + %result = tuple.from_elements %i, %f : tuple + return %result : tuple } func.func @map_add_field() { iterators.print ("map_add_field") %input = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32]] } - : () -> (!iterators.stream) + : () -> (!iterators.stream>) %mapped = "iterators.map"(%input) {mapFuncRef = @add_field} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%mapped) : (!iterators.stream) -> () + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%mapped) : (!iterators.stream>) -> () // CHECK-LABEL: map_add_field // CHECK-NEXT: (0, 0) // CHECK-NEXT: (1, 1) @@ -59,8 +54,8 @@ func.func @map_add_field() { return } -func.func private @unpack_i32(%input : !i32_struct) -> i32 { - %i = llvm.extractvalue %input[0] : !i32_struct +func.func private @unpack_i32(%input : tuple) -> i32 { + %i = tuple.to_elements %input : tuple return %i : i32 } @@ -68,9 +63,9 @@ func.func @map_unpack_pack() { iterators.print ("map_unpack_pack") %input = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32]] } - : () -> (!iterators.stream) + : () -> (!iterators.stream>) %unpacked = "iterators.map"(%input) {mapFuncRef = @unpack_i32} - : (!iterators.stream) -> (!iterators.stream) + : (!iterators.stream>) -> (!iterators.stream) "iterators.sink"(%unpacked) : (!iterators.stream) -> () // CHECK-LABEL: map_unpack_pack // CHECK-NEXT: 0 @@ -81,7 +76,7 @@ func.func @map_unpack_pack() { } func.func @main() { - call @map_double_struct() : () -> () + call @map_double_tuple() : () -> () call @map_add_field() : () -> () call @map_unpack_pack() : () -> () return diff --git a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/reduce.mlir b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/reduce.mlir index a71e100278b7..86657339565c 100644 --- a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/reduce.mlir +++ b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/reduce.mlir @@ -1,30 +1,29 @@ // RUN: iterators-opt %s \ // RUN: -convert-iterators-to-llvm \ +// RUN: -decompose-tuples \ // RUN: -decompose-iterator-states -canonicalize \ // RUN: -convert-func-to-llvm \ // RUN: -convert-scf-to-cf -convert-cf-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ // RUN: | FileCheck %s -!i32_struct = !llvm.struct<(i32)> - -func.func private @sum_struct(%lhs : !i32_struct, %rhs : !i32_struct) -> !i32_struct { - %lhsi = llvm.extractvalue %lhs[0] : !i32_struct - %rhsi = llvm.extractvalue %rhs[0] : !i32_struct +func.func private @sum_tuple(%lhs : tuple, %rhs : tuple) -> tuple { + %lhsi = tuple.to_elements %lhs : tuple + %rhsi = tuple.to_elements %rhs : tuple %i = arith.addi %lhsi, %rhsi : i32 - %result = llvm.insertvalue %i, %lhs[0] : !i32_struct - return %result : !i32_struct + %result = tuple.from_elements %i : tuple + return %result : tuple } -func.func @reduce_sum_struct() { - iterators.print ("reduce_sum_struct") +func.func @reduce_sum_tuple() { + iterators.print ("reduce_sum_tuple") %input = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32], [3 : i32]] } - : () -> (!iterators.stream) - %reduced = "iterators.reduce"(%input) {reduceFuncRef = @sum_struct} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%reduced) : (!iterators.stream) -> () - // CHECK-LABEL: reduce_sum_struct + : () -> (!iterators.stream>) + %reduced = "iterators.reduce"(%input) {reduceFuncRef = @sum_tuple} + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%reduced) : (!iterators.stream>) -> () + // CHECK-LABEL: reduce_sum_tuple // CHECK-NEXT: (6) // CHECK-NEXT: - return @@ -35,8 +34,8 @@ func.func private @sum_i32(%lhs : i32, %rhs : i32) -> i32 { return %result : i32 } -func.func private @unpack_i32(%input : !i32_struct) -> i32 { - %i = llvm.extractvalue %input[0] : !i32_struct +func.func private @unpack_i32(%input : tuple) -> i32 { + %i = tuple.to_elements %input : tuple return %i : i32 } @@ -44,9 +43,9 @@ func.func @reduce_sum_i32() { iterators.print ("reduce_sum_i32") %input = "iterators.constantstream"() { value = [[0 : i32], [10 : i32], [20 : i32], [30 : i32]] } - : () -> (!iterators.stream) + : () -> (!iterators.stream>) %unpacked = "iterators.map"(%input) {mapFuncRef = @unpack_i32} - : (!iterators.stream) -> (!iterators.stream) + : (!iterators.stream>) -> (!iterators.stream) %reduced = "iterators.reduce"(%unpacked) {reduceFuncRef = @sum_i32} : (!iterators.stream) -> (!iterators.stream) "iterators.sink"(%reduced) : (!iterators.stream) -> () @@ -56,20 +55,18 @@ func.func @reduce_sum_i32() { return } -!i32f32_struct = !llvm.struct<(i32, f32)> - -// Return input where second struct field is larger. Return lhs on equality or +// Return input where second tuple element is larger. Return lhs on equality or // unordered. -func.func private @arg_max(%lhs : !i32f32_struct, %rhs : !i32f32_struct) -> !i32f32_struct { - %lhsf = llvm.extractvalue %lhs[1] : !i32f32_struct - %rhsf = llvm.extractvalue %rhs[1] : !i32f32_struct +func.func private @arg_max(%lhs : tuple, %rhs : tuple) -> tuple { + %lhsi, %lhsf = tuple.to_elements %lhs : tuple + %rhsi, %rhsf = tuple.to_elements %rhs : tuple %cmp = arith.cmpf "uge", %lhsf, %rhsf : f32 - %result = scf.if %cmp -> !i32f32_struct { - scf.yield %lhs : !i32f32_struct + %result = scf.if %cmp -> tuple { + scf.yield %lhs : tuple } else { - scf.yield %rhs : !i32f32_struct + scf.yield %rhs : tuple } - return %result : !i32f32_struct + return %result : tuple } func.func @reduce_arg_max() { @@ -78,10 +75,10 @@ func.func @reduce_arg_max() { { value = [[0 : i32, 0. : f32], [1 : i32, 13.37 : f32], // <-- max value [2 : i32, 4.2 : f32]] } - : () -> (!iterators.stream) + : () -> (!iterators.stream>) %reduce = "iterators.reduce"(%input) {reduceFuncRef = @arg_max} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%reduce) : (!iterators.stream) -> () + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%reduce) : (!iterators.stream>) -> () // CHECK-LABEL: reduce_arg_max // CHECK-NEXT: (1, 13.37) // CHECK-NEXT: - @@ -89,7 +86,7 @@ func.func @reduce_arg_max() { } func.func @main() { - call @reduce_sum_struct() : () -> () + call @reduce_sum_tuple() : () -> () call @reduce_sum_i32() : () -> () call @reduce_arg_max() : () -> () return diff --git a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/symbol-collision-resolution.mlir b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/symbol-collision-resolution.mlir index 2f01f3714291..14aee2c1c17a 100644 --- a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/symbol-collision-resolution.mlir +++ b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/symbol-collision-resolution.mlir @@ -1,19 +1,18 @@ // RUN: iterators-opt %s \ // RUN: -convert-iterators-to-llvm \ // RUN: -decompose-iterator-states -canonicalize \ +// RUN: -decompose-tuples \ // RUN: -convert-func-to-llvm \ // RUN: -convert-scf-to-cf -convert-cf-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ // RUN: | FileCheck %s -!element_type = !llvm.struct<(i32)> - -func.func private @sum_struct(%lhs : !element_type, %rhs : !element_type) -> !element_type { - %lhsi = llvm.extractvalue %lhs[0] : !element_type - %rhsi = llvm.extractvalue %rhs[0] : !element_type +func.func private @sum_tuple(%lhs : tuple, %rhs : tuple) -> tuple { + %lhsi = tuple.to_elements %lhs : tuple + %rhsi = tuple.to_elements %rhs : tuple %i = arith.addi %lhsi, %rhsi : i32 - %result = llvm.insertvalue %i, %lhs[0] : !element_type - return %result : !element_type + %result = tuple.from_elements %i : tuple + return %result : tuple } func.func @query1() { @@ -22,13 +21,13 @@ func.func @query1() { // CHECK-NEXT: - iterators.print ("query1") %input = "iterators.constantstream"() { value = [[6 : i32]] } - : () -> (!iterators.stream) - %reduce1 = "iterators.reduce"(%input) {reduceFuncRef = @sum_struct} - : (!iterators.stream) -> (!iterators.stream) + : () -> (!iterators.stream>) + %reduce1 = "iterators.reduce"(%input) {reduceFuncRef = @sum_tuple} + : (!iterators.stream>) -> (!iterators.stream>) // Reduce result again to vary from second query. - %reduce2 = "iterators.reduce"(%reduce1) {reduceFuncRef = @sum_struct} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%reduce2) : (!iterators.stream) -> () + %reduce2 = "iterators.reduce"(%reduce1) {reduceFuncRef = @sum_tuple} + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%reduce2) : (!iterators.stream>) -> () return } @@ -40,10 +39,10 @@ func.func @query2() { // Run similar query again to check that name collision resolution works. %input = "iterators.constantstream"(){ value = [[6 : i32]] } - : () -> (!iterators.stream) - %reduce = "iterators.reduce"(%input) {reduceFuncRef = @sum_struct} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%reduce) : (!iterators.stream) -> () + : () -> (!iterators.stream>) + %reduce = "iterators.reduce"(%input) {reduceFuncRef = @sum_tuple} + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%reduce) : (!iterators.stream>) -> () return } func.func @main() { diff --git a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/tpch-q6.mlir b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/tpch-q6.mlir index d49d97c8cd2f..cd1c5aebd184 100644 --- a/experimental/iterators/test/Integration/Dialect/Iterators/CPU/tpch-q6.mlir +++ b/experimental/iterators/test/Integration/Dialect/Iterators/CPU/tpch-q6.mlir @@ -1,6 +1,7 @@ // RUN: iterators-opt %s \ // RUN: -convert-iterators-to-llvm \ // RUN: -decompose-iterator-states -canonicalize \ +// RUN: -decompose-tuples \ // RUN: -convert-func-to-llvm \ // RUN: -convert-scf-to-cf -convert-cf-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ @@ -33,10 +34,9 @@ // - 0.06 + 0.01 (l_discount): 7 : i8 // - 24 (l_quantity): 24 : i8 -func.func private @q6_predicate(%input : !llvm.struct<(i8,i32,i8,i16)>) -> i1 { - %quantity = llvm.extractvalue %input[0] : !llvm.struct<(i8,i32,i8,i16)> - %discount = llvm.extractvalue %input[2] : !llvm.struct<(i8,i32,i8,i16)> - %shipdate = llvm.extractvalue %input[3] : !llvm.struct<(i8,i32,i8,i16)> +func.func private @q6_predicate(%input : tuple) -> i1 { + %quantity, %extendedprice, %discount, %shipdate = + tuple.to_elements %input : tuple // Test lower bound on shipdate. %c8766 = arith.constant 8677 : i16 @@ -76,9 +76,9 @@ func.func private @q6_predicate(%input : !llvm.struct<(i8,i32,i8,i16)>) -> i1 { return %result : i1 } -func.func private @compute_discounted_price(%input : !llvm.struct<(i8,i32,i8,i16)>) -> i32 { - %extendedprice = llvm.extractvalue %input[1] : !llvm.struct<(i8,i32,i8,i16)> - %discount = llvm.extractvalue %input[2] : !llvm.struct<(i8,i32,i8,i16)> +func.func private @compute_discounted_price(%input : tuple) -> i32 { + %quantity, %extendedprice, %discount, %shipdate = + tuple.to_elements %input : tuple %discount_i32 = llvm.zext %discount : i8 to i32 %result = arith.muli %extendedprice, %discount_i32 : i32 return %result : i32 @@ -100,16 +100,16 @@ func.func @main() { [ 11 : i8, 1847703 : i32, 1 : i8, 8841 : i16 ], [ 37 : i8, 3952081 : i32, 9 : i8, 8809 : i16 ], [ 19 : i8, 3060235 : i32, 6 : i8, 8791 : i16 ]] } - : () -> (!iterators.stream>) + : () -> (!iterators.stream>) // Apply filter from WHERE clause. %filtered = "iterators.filter"(%lineitem) { predicateRef = @q6_predicate } - : (!iterators.stream>) - -> (!iterators.stream>) + : (!iterators.stream>) + -> (!iterators.stream>) // Project to l_extendedprice * l_discount (in 1/100 cents). %mapped = "iterators.map"(%filtered) { mapFuncRef = @compute_discounted_price } - : (!iterators.stream>) + : (!iterators.stream>) -> (!iterators.stream) // Sum up values. diff --git a/experimental/iterators/test/python/dialects/iterators/dialect.py b/experimental/iterators/test/python/dialects/iterators/dialect.py index 949056267f0f..75bf33185255 100644 --- a/experimental/iterators/test/python/dialects/iterators/dialect.py +++ b/experimental/iterators/test/python/dialects/iterators/dialect.py @@ -8,6 +8,7 @@ from mlir_iterators.runtime.pandas_to_iterators import to_tabular_view_descriptor from mlir_iterators.dialects import iterators as it from mlir_iterators.dialects import tabular as tab +from mlir_iterators.dialects import tuple as tup from mlir_iterators.passmanager import PassManager from mlir_iterators.execution_engine import ExecutionEngine from mlir_iterators.ir import Context, Module, IntegerType @@ -18,6 +19,7 @@ def run(f): with Context(): it.register_dialect() tab.register_dialect() + tup.register_dialect() f() return f @@ -35,10 +37,10 @@ def testStreamType(): # CHECK-LABEL: TEST: testParse def testParse(): mod = Module.parse( - '%0 = "iterators.constantstream"() {value = []} : () -> (!iterators.stream>)' + '%0 = "iterators.constantstream"() {value = []} : () -> (!iterators.stream>)' ) # CHECK: module { - # CHECK-NEXT: %[[V0:.*]] = "iterators.constantstream"() {value = []} : () -> !iterators.stream> + # CHECK-NEXT: %[[V0:.*]] = "iterators.constantstream"() {value = []} : () -> !iterators.stream> # CHECK-NEXT: } print(mod) @@ -48,7 +50,7 @@ def testParse(): def testConvertIteratorsToLlvm(): mod = Module.parse(''' func.func @main() { - %0 = "iterators.constantstream"() {value = []} : () -> (!iterators.stream>) + %0 = "iterators.constantstream"() {value = []} : () -> (!iterators.stream>) return } ''') @@ -62,21 +64,20 @@ def testConvertIteratorsToLlvm(): # CHECK-LABEL: TEST: testEndToEndStandalone def testEndToEndStandalone(): mod = Module.parse(''' - !element_type = !llvm.struct<(i32)> - func.func private @sum_struct(%lhs : !element_type, %rhs : !element_type) -> !element_type { - %lhsi = llvm.extractvalue %lhs[0] : !element_type - %rhsi = llvm.extractvalue %rhs[0] : !element_type + func.func private @sum_tuple(%lhs : tuple, %rhs : tuple) -> tuple { + %lhsi = tuple.to_elements %lhs : tuple + %rhsi = tuple.to_elements %rhs : tuple %i = arith.addi %lhsi, %rhsi : i32 - %result = llvm.insertvalue %i, %lhs[0] : !element_type - return %result : !element_type + %result = tuple.from_elements %i : tuple + return %result : tuple } func.func @main() attributes { llvm.emit_c_interface } { %input = "iterators.constantstream"() { value = [[0 : i32], [1 : i32], [2 : i32], [3 : i32]] } : - () -> (!iterators.stream) - %reduce = "iterators.reduce"(%input) {reduceFuncRef = @sum_struct} - : (!iterators.stream) -> (!iterators.stream) - "iterators.sink"(%reduce) : (!iterators.stream) -> () + () -> (!iterators.stream>) + %reduce = "iterators.reduce"(%input) {reduceFuncRef = @sum_tuple} + : (!iterators.stream>) -> (!iterators.stream>) + "iterators.sink"(%reduce) : (!iterators.stream>) -> () return } ''') @@ -84,6 +85,7 @@ def testEndToEndStandalone(): 'convert-iterators-to-llvm,' 'decompose-iterator-states,' 'canonicalize,' + 'decompose-tuples,' 'convert-func-to-llvm,' 'convert-scf-to-cf,' 'convert-cf-to-llvm)')