diff --git a/mlir/include/mlir/Transforms/Bufferize.h b/mlir/include/mlir/Transforms/Bufferize.h --- a/mlir/include/mlir/Transforms/Bufferize.h +++ b/mlir/include/mlir/Transforms/Bufferize.h @@ -51,36 +51,6 @@ BufferizeTypeConverter(); - /// This method tries to decompose a value of a certain type using provided - /// decompose callback functions. If it is unable to do so, the original value - /// is returned. - void tryDecomposeValue(OpBuilder &, Location, Type, Value, - SmallVectorImpl &); - - /// This method tries to decompose a type using provided decompose callback - /// functions. If it is unable to do so, the original type is returned. - void tryDecomposeType(Type, SmallVectorImpl &); - - /// This method registers a callback function that will be called to decompose - /// a value of a certain type into several values. - template ::template arg_t<2>> - void addDecomposeValueConversion(FnT &&callback) { - decomposeValueConversions.emplace_back( - wrapDecomposeValueConversionCallback(std::forward(callback))); - } - - /// This method registers a callback function that will be called to decompose - /// a type into several types. - template ::template arg_t<0>> - void addDecomposeTypeConversion(FnT &&callback) { - auto wrapper = - wrapDecomposeTypeConversionCallback(std::forward(callback)); - decomposeTypeConversions.emplace_back(wrapper); - addConversion(std::forward(callback)); - } - /// This method returns ResultConversionKind for the mapping from `origin` /// type to `input` type. ResultConversionKind getResultConversionKind(Type origin, Type input); @@ -102,45 +72,10 @@ } private: - using DecomposeValueConversionCallFn = std::function( - OpBuilder &, Location, Type, Value, SmallVectorImpl &)>; - - using DecomposeTypeConversionCallFn = - std::function(Type, SmallVectorImpl &)>; - using ResultConversionKindFn = std::function(Type, Type)>; - /// Generate a wrapper for the given decompose value conversion callback. - template - DecomposeValueConversionCallFn - wrapDecomposeValueConversionCallback(FnT &&callback) { - return [callback = std::forward(callback)]( - OpBuilder &builder, Location loc, Type type, Value value, - SmallVectorImpl &newValues) -> Optional { - if (T derivedType = type.dyn_cast()) - return callback(builder, loc, derivedType, value, newValues); - return llvm::None; - }; - } - - /// Generate a wrapper for the given decompose type conversion callback. - template - DecomposeTypeConversionCallFn - wrapDecomposeTypeConversionCallback(FnT &&callback) { - return [callback = std::forward(callback)]( - Type type, - SmallVectorImpl &results) -> Optional { - T derivedType = type.dyn_cast(); - if (!derivedType) - return llvm::None; - return callback(derivedType, results); - }; - } - SmallVector resultTypeConversions; - SmallVector decomposeValueConversions; - SmallVector decomposeTypeConversions; }; /// Marks ops used by bufferization for type conversion materializations as @@ -218,23 +153,16 @@ // decomposable and a decompose callback function has been provided by the // user, it will be unpacked. SmallVector newOperands, needCopyOperands; - OpBuilder builder(returnOp); - for (auto operand : llvm::enumerate(operands)) { - SmallVector values; - this->converter.tryDecomposeValue(builder, loc, operand.value().getType(), - operand.value(), values); - Type type = returnOp.getOperand(operand.index()).getType(); - SmallVector originTypes; - this->converter.tryDecomposeType(type, originTypes); - for (auto value : llvm::enumerate(values)) { - Type origin = originTypes[value.index()]; - Type converted = value.value().getType(); - auto kind = this->converter.getResultConversionKind(origin, converted); - if (kind == BufferizeTypeConverter::KeepAsFunctionResult) - newOperands.push_back(value.value()); - else - // kind = BufferizeTypeConverter::AppendToArgumentsList - needCopyOperands.push_back(value.value()); + for (auto t : llvm::zip(returnOp.getOperands(), operands)) { + auto originalOperand = std::get<0>(t); + auto convertedOperand = std::get<1>(t); + auto kind = this->converter.getResultConversionKind( + originalOperand.getType(), convertedOperand.getType()); + if (kind == BufferizeTypeConverter::KeepAsFunctionResult) { + newOperands.push_back(convertedOperand); + } else { + assert(kind == BufferizeTypeConverter::AppendToArgumentsList); + needCopyOperands.push_back(convertedOperand); } } diff --git a/mlir/lib/Transforms/Bufferize.cpp b/mlir/lib/Transforms/Bufferize.cpp --- a/mlir/lib/Transforms/Bufferize.cpp +++ b/mlir/lib/Transforms/Bufferize.cpp @@ -41,28 +41,6 @@ }); } -/// This method tries to decompose a value of a certain type using provided -/// decompose callback functions. If it is unable to do so, the original value -/// is returned. -void BufferizeTypeConverter::tryDecomposeValue( - OpBuilder &builder, Location loc, Type type, Value value, - SmallVectorImpl &results) { - for (auto &conversion : decomposeValueConversions) - if (conversion(builder, loc, type, value, results)) - return; - results.push_back(value); -} - -/// This method tries to decompose a type using provided decompose callback -/// functions. If it is unable to do so, the original type is returned. -void BufferizeTypeConverter::tryDecomposeType(Type type, - SmallVectorImpl &types) { - for (auto &conversion : decomposeTypeConversions) - if (conversion(type, types)) - return; - types.push_back(type); -} - /// This method returns ResultConversionKind for the input type. BufferizeTypeConverter::ResultConversionKind BufferizeTypeConverter::getResultConversionKind(Type origin, Type converted) { @@ -88,28 +66,21 @@ // Convert function arguments using the provided TypeConverter. TypeConverter::SignatureConversion conversion(funcType.getNumInputs()); - for (auto argType : llvm::enumerate(funcType.getInputs())) { - SmallVector decomposedTypes, convertedTypes; - converter.tryDecomposeType(argType.value(), decomposedTypes); - converter.convertTypes(decomposedTypes, convertedTypes); - conversion.addInputs(argType.index(), convertedTypes); - } + for (auto argType : llvm::enumerate(funcType.getInputs())) + conversion.addInputs(argType.index(), + converter.convertType(argType.value())); // Convert the result types of the function. SmallVector newResultTypes; newResultTypes.reserve(funcOp.getNumResults()); for (Type resultType : funcType.getResults()) { - SmallVector originTypes; - converter.tryDecomposeType(resultType, originTypes); - for (auto origin : originTypes) { - Type converted = converter.convertType(origin); - auto kind = converter.getResultConversionKind(origin, converted); - if (kind == BufferizeTypeConverter::AppendToArgumentsList) { - conversion.addInputs(converted); - } else { - assert(kind == BufferizeTypeConverter::KeepAsFunctionResult); - newResultTypes.push_back(converted); - } + Type converted = converter.convertType(resultType); + auto kind = converter.getResultConversionKind(resultType, converted); + if (kind == BufferizeTypeConverter::AppendToArgumentsList) { + conversion.addInputs(converted); + } else { + assert(kind == BufferizeTypeConverter::KeepAsFunctionResult); + newResultTypes.push_back(converted); } } @@ -196,68 +167,39 @@ // convert if some special attribute is set. // This will allow more control of interop across ABI boundaries. - // Create the operands list of the new `CallOp`. It unpacks the decomposable - // values if a decompose callback function has been provided by the user. - for (auto operand : operands) { - SmallVector values; - converter.tryDecomposeValue(builder, loc, operand.getType(), operand, - values); - newOperands.append(values.begin(), values.end()); - } + // Create the operands list of the new `CallOp`. + newOperands.append(operands.begin(), operands.end()); // Create the new result types for the new `CallOp` and a mapping from the old - // result to new value(s). + // result to new value. SmallVector newResultTypes; - SmallVector mappings; - mappings.resize(callOp.getNumResults()); - for (auto result : llvm::enumerate(callOp.getResults())) { - SmallVector originTypes; - converter.tryDecomposeType(result.value().getType(), originTypes); - auto &resultMapping = mappings[result.index()]; - for (Type origin : originTypes) { - Type converted = converter.convertType(origin); - auto kind = converter.getResultConversionKind(origin, converted); - if (kind == BufferizeTypeConverter::KeepAsFunctionResult) { - newResultTypes.push_back(converted); - // The result value is not yet available. Its index is kept and it is - // replaced with the actual value of the new `CallOp` later. - resultMapping.addMapping(newResultTypes.size() - 1); - } else { - // kind = BufferizeTypeConverter::AppendToArgumentsList - MemRefType memref = converted.dyn_cast(); - if (!memref) - return callOp.emitError("Cannot allocate for a non-Memref type"); - Value alloc = rewriter.create(loc, memref); - newOperands.push_back(alloc); - resultMapping.addMapping(alloc); - } + CallOpResultMapping resultMapping; + for (auto result : callOp.getResults()) { + Type converted = converter.convertType(result.getType()); + auto kind = converter.getResultConversionKind(result.getType(), converted); + if (kind == BufferizeTypeConverter::KeepAsFunctionResult) { + newResultTypes.push_back(converted); + // The result value is not yet available. Its index is kept and it is + // replaced with the actual value of the new `CallOp` later. + resultMapping.addMapping(newResultTypes.size() - 1); + } else { + assert(kind == BufferizeTypeConverter::AppendToArgumentsList); + MemRefType memref = converted.dyn_cast(); + if (!memref || !memref.hasStaticShape()) + return callOp.emitError( + "Only static shape memrefs can become out-params"); + Value alloc = rewriter.create(loc, memref); + newOperands.push_back(alloc); + resultMapping.addMapping(alloc); } } CallOp newCallOp = rewriter.create(loc, callOp.getCallee(), newResultTypes, newOperands); - // Build a replacing value for each result to replace its uses. If a result - // has multiple mapping values, it needs to be packed to a single value. - OpBuilder nextBuilder(callOp.getOperation()->getNextNode()); + // Build a replacing value for each result to replace its uses. SmallVector replacedValues; - replacedValues.reserve(callOp.getNumResults()); - for (unsigned i = 0, e = callOp.getNumResults(); i < e; ++i) { - SmallVector valuesToPack; - mappings[i].getMappingValues(newCallOp.getResults(), valuesToPack); - if (valuesToPack.empty()) { - // No replacement is required. - replacedValues.push_back(nullptr); - } else if (valuesToPack.size() == 1) { - replacedValues.push_back(valuesToPack.front()); - } else { - // Values need to be packed using callback function. The same callback - // that is used for materializeArgumentConversion is used for packing. - Value packed = converter.materializeArgumentConversion( - nextBuilder, loc, callOp.getType(i), valuesToPack); - replacedValues.push_back(packed); - } - } + resultMapping.getMappingValues(newCallOp.getResults(), replacedValues); rewriter.replaceOp(callOp, replacedValues); return success(); } diff --git a/mlir/test/Transforms/finalizing-bufferize-allowed-memref-results.mlir b/mlir/test/Transforms/finalizing-bufferize-allowed-memref-results.mlir --- a/mlir/test/Transforms/finalizing-bufferize-allowed-memref-results.mlir +++ b/mlir/test/Transforms/finalizing-bufferize-allowed-memref-results.mlir @@ -99,74 +99,3 @@ // CHECK: %[[X:.*]]:2 = call @callee(%[[CALLER_ARG]]) // CHECK: %[[Y:.*]]:2 = call @callee(%[[X]]#0) // CHECK: return %[[Y]]#0 - -// ----- - -// Test case: Testing BufferizeCallOpConverter to see if it matches with the -// signature of the new signature of the callee function when there are tuple typed -// args and results. BufferizeTypeConverter is set to flatten tuple typed -// arguments. The tuple typed values should be decomposed and composed using -// get_tuple_element and make_tuple operations of test dialect. Tensor types are -// converted to Memref. Memref typed function results remain as function results. - -// CHECK-LABEL: func @callee -func @callee(%arg0: tuple,i1, tensor<5xf32>>) -> (tuple,i1, tensor<5xf32>>){ - return %arg0 : tuple,i1, tensor<5xf32>> -} -// CHECK-SAME: (%[[ARG0:.*]]: memref<2xf32>, %[[ARG1:.*]]: i1, %[[ARG2:.*]]: memref<5xf32>) -// CHECK-SAME: (memref<2xf32>, i1, memref<5xf32>) -// CHECK-NEXT: %[[TUPLE:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]], %[[ARG2]]) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: return %[[FIRST_ELEM]], %[[SECOND_ELEM]], %[[THIRD_ELEM]] - -// CHECK-LABEL: func @caller -func @caller(%arg0: tuple,i1, tensor<5xf32>>) -> tuple,i1, tensor<5xf32>>{ - %x0 = call @callee(%arg0) : (tuple,i1, tensor<5xf32>>) -> (tuple,i1, tensor<5xf32>>) - %y0 = call @callee(%x0) : (tuple,i1, tensor<5xf32>>) -> (tuple,i1, tensor<5xf32>>) - return %y0 : tuple,i1, tensor<5xf32>> -} -// CHECK-SAME: (%[[ARG0:.*]]: memref<2xf32>, %[[ARG1:.*]]: i1, %[[ARG2:.*]]: memref<5xf32>) -// CHECK-SAME: (memref<2xf32>, i1, memref<5xf32>) -// CHECK-NEXT: %[[ARG_TUPLE:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]], %[[ARG2]]) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[ARG_TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[ARG_TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[ARG_TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: %[[CALLEE_RESULTS:.*]]:3 = call @callee(%[[FIRST_ELEM]], %[[SECOND_ELEM]], %[[THIRD_ELEM]]) -// CHECK-SAME: (memref<2xf32>, i1, memref<5xf32>) -> (memref<2xf32>, i1, memref<5xf32>) -// CHECK-NEXT: %[[RESULT_TUPLE:.*]] = "test.make_tuple"(%[[CALLEE_RESULTS]]#0, %[[CALLEE_RESULTS]]#1, %[[CALLEE_RESULTS]]#2) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[RESULT_TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[RESULT_TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[RESULT_TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: %[[CALLEE_RESULTS:.*]]:3 = call @callee(%[[FIRST_ELEM]], %[[SECOND_ELEM]], %[[THIRD_ELEM]]) -// CHECK-SAME: (memref<2xf32>, i1, memref<5xf32>) -> (memref<2xf32>, i1, memref<5xf32>) -// CHECK-NEXT: %[[RETURN_TUPLE:.*]] = "test.make_tuple"(%[[CALLEE_RESULTS]]#0, %[[CALLEE_RESULTS]]#1, %[[CALLEE_RESULTS]]#2) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[RETURN_TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[RETURN_TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[RETURN_TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: return %[[FIRST_ELEM]], %[[SECOND_ELEM]], %[[THIRD_ELEM]] - -// ----- - -// Test case: Testing BufferizeFuncOpConverter and -// BufferizeReturnOpConverter to see if the return operation matches with -// the new function signature when there are tuple typed args and results. -// BufferizeTypeConverter is set to flatten tuple typed arguments. The tuple -// typed values should be decomposed and composed using get_tuple_element and -// make_tuple operations of test dialect. Tensor types are converted to Memref. -// Memref typed function results remain as function results. - -// CHECK-LABEL: func @decompose_tuple_typed_function_args_and_results -func @decompose_tuple_typed_function_args_and_results(%arg0: tuple, %arg1: tensor<10xf32>, %arg2: tuple>) -> (tuple>, tensor<10xf32>, tuple){ - return %arg2, %arg1, %arg0 : tuple>, tensor<10xf32>, tuple -} -// CHECK-SAME: %[[ARG0:.*]]: i1, %[[ARG1:.*]]: f32, %[[ARG2:.*]]: memref<10xf32>, %[[ARG3:.*]]: i1, %[[ARG4:.*]]: memref<5xf32> -// CHECK-SAME: (i1, memref<5xf32>, memref<10xf32>, i1, f32) -// CHECK-NEXT: %[[FIRST_TUPLE:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]]) -// CHECK-NEXT: %[[SECOND_TUPLE:.*]] = "test.make_tuple"(%[[ARG3]], %[[ARG4]]) -// CHECK-NEXT: %[[SECOND_TUPLE_FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[SECOND_TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_TUPLE_SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[SECOND_TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[FIRST_TUPLE_FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[FIRST_TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[FIRST_TUPLE_SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[FIRST_TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: return %[[SECOND_TUPLE_FIRST_ELEM]], %[[SECOND_TUPLE_SECOND_ELEM]], %[[ARG2]], %[[FIRST_TUPLE_FIRST_ELEM]], %[[FIRST_TUPLE_SECOND_ELEM]] diff --git a/mlir/test/Transforms/finalizing-bufferize.mlir b/mlir/test/Transforms/finalizing-bufferize.mlir --- a/mlir/test/Transforms/finalizing-bufferize.mlir +++ b/mlir/test/Transforms/finalizing-bufferize.mlir @@ -167,86 +167,3 @@ return } // CHECK-SAME: ([[ARG:%.*]]: memref<*xf32>) - -// ----- - -// Test case: Testing BufferizeCallOpConverter to see if it matches with the -// signature of the new signature of the callee function when there are tuple typed -// args and results. BufferizeTypeConverter is set to flatten tuple typed -// arguments. The tuple typed values should be decomposed and composed using -// get_tuple_element and make_tuple operations of test dialect. Tensor types are -// converted to Memref. Memref typed function results are appended to the function -// arguments list. - -// CHECK-LABEL: func @callee -func @callee(%arg0: tuple,i1, tensor<5xf32>>) -> (tuple,i1, tensor<5xf32>>){ - return %arg0 : tuple,i1, tensor<5xf32>> -} -// CHECK-SAME: (%[[ARG0:.*]]: memref<2xf32>, %[[ARG1:.*]]: i1, %[[ARG2:.*]]: memref<5xf32>, %[[RESULT0:.*]]: memref<2xf32>, %[[RESULT1:.*]]: memref<5xf32>) -// CHECK-SAME: i1 -// CHECK-NEXT: %[[TUPLE:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]], %[[ARG2]]) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: linalg.copy(%[[FIRST_ELEM]], %[[RESULT0]]) -// CHECK-NEXT: linalg.copy(%[[THIRD_ELEM]], %[[RESULT1]]) -// CHECK-NEXT: return %[[SECOND_ELEM]] - - -// CHECK-LABEL: func @caller -func @caller(%arg0: tuple,i1, tensor<5xf32>>) -> tuple,i1, tensor<5xf32>>{ - %x0 = call @callee(%arg0) : (tuple,i1, tensor<5xf32>>) -> (tuple,i1, tensor<5xf32>>) - %y0 = call @callee(%x0) : (tuple,i1, tensor<5xf32>>) -> (tuple,i1, tensor<5xf32>>) - return %y0 : tuple,i1, tensor<5xf32>> -} -// CHECK-SAME: (%[[ARG0:.*]]: memref<2xf32>, %[[ARG1:.*]]: i1, %[[ARG2:.*]]: memref<5xf32>, %[[RESULT0:.*]]: memref<2xf32>, %[[RESULT1:.*]]: memref<5xf32>) -// CHECK-SAME: i1 -// CHECK-NEXT: %[[TUPLE:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]], %[[ARG2]]) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: %[[FIRST_ALLOC:.*]] = alloc() -// CHECK-NEXT: %[[SECOND_ALLOC:.*]] = alloc() -// CHECK-NEXT: %[[CALLEE_RESULT:.*]] = call @callee(%[[FIRST_ELEM]], %[[SECOND_ELEM]], %[[THIRD_ELEM]], %[[FIRST_ALLOC]], %[[SECOND_ALLOC]]) -// CHECK-SAME: (memref<2xf32>, i1, memref<5xf32>, memref<2xf32>, memref<5xf32>) -> i1 -// CHECK-NEXT: %[[TUPLE:.*]] = "test.make_tuple"(%[[FIRST_ALLOC]], %[[CALLEE_RESULT]], %[[SECOND_ALLOC]]) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: %[[FIRST_ALLOC:.*]] = alloc() -// CHECK-NEXT: %[[SECOND_ALLOC:.*]] = alloc() -// CHECK-NEXT: %[[CALLEE_RESULT:.*]] = call @callee(%[[FIRST_ELEM]], %[[SECOND_ELEM]], %[[THIRD_ELEM]], %[[FIRST_ALLOC]], %[[SECOND_ALLOC]]) -// CHECK-SAME: (memref<2xf32>, i1, memref<5xf32>, memref<2xf32>, memref<5xf32>) -> i1 -// CHECK-NEXT: %[[TUPLE:.*]] = "test.make_tuple"(%[[FIRST_ALLOC]], %[[CALLEE_RESULT]], %[[SECOND_ALLOC]]) -// CHECK-NEXT: %[[FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[THIRD_ELEM:.*]] = "test.get_tuple_element"(%[[TUPLE]]) {index = 2 : i32} -// CHECK-NEXT: linalg.copy(%[[FIRST_ELEM]], %[[RESULT0]]) -// CHECK-NEXT: linalg.copy(%[[THIRD_ELEM]], %[[RESULT1]]) -// CHECK-NEXT: return %[[SECOND_ELEM]] - -// ----- - -// Test case: Testing BufferizeFuncOpConverter and -// BufferizeReturnOpConverter to see if the return operation matches with -// the new function signature when there are tuple typed args and results. -// BufferizeTypeConverter is set to flatten tuple typed arguments. The tuple -// typed values should be decomposed and composed using get_tuple_element and -// make_tuple operations of test dialect. Tensor types are converted to Memref. -// Memref typed function results are appended to the function arguments list. - -// CHECK-LABEL: func @decompose_tuple_typed_function_args_and_results -func @decompose_tuple_typed_function_args_and_results(%arg0: tuple, %arg1: tensor<10xf32>, %arg2: tuple>) -> (tuple>, tensor<10xf32>, tuple){ - return %arg2, %arg1, %arg0 : tuple>, tensor<10xf32>, tuple -} -// CHECK-SAME: %[[ARG0:.*]]: i1, %[[ARG1:.*]]: f32, %[[ARG2:.*]]: memref<10xf32>, %[[ARG3:.*]]: i1, %[[ARG4:.*]]: memref<5xf32>, %[[RESULT0:.*]]: memref<5xf32>, %[[RESULT1:.*]]: memref<10xf32> -// CHECK-SAME: (i1, i1, f32) -// CHECK-NEXT: %[[FIRST_TUPLE:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]]) -// CHECK-NEXT: %[[SECOND_TUPLE:.*]] = "test.make_tuple"(%[[ARG3]], %[[ARG4]]) -// CHECK-NEXT: %[[SECOND_TUPLE_FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[SECOND_TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[SECOND_TUPLE_SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[SECOND_TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: %[[FIRST_TUPLE_FIRST_ELEM:.*]] = "test.get_tuple_element"(%[[FIRST_TUPLE]]) {index = 0 : i32} -// CHECK-NEXT: %[[FIRST_TUPLE_SECOND_ELEM:.*]] = "test.get_tuple_element"(%[[FIRST_TUPLE]]) {index = 1 : i32} -// CHECK-NEXT: linalg.copy(%[[SECOND_TUPLE_SECOND_ELEM]], %[[RESULT0]]) -// CHECK-NEXT: linalg.copy(%[[ARG2]], %[[RESULT1]]) -// CHECK-NEXT: return %[[SECOND_TUPLE_FIRST_ELEM]], %[[FIRST_TUPLE_FIRST_ELEM]], %[[FIRST_TUPLE_SECOND_ELEM]] diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -1787,31 +1787,4 @@ }]; } -//===----------------------------------------------------------------------===// -// Test BufferPlacement -//===----------------------------------------------------------------------===// - -def GetTupleElementOp: TEST_Op<"get_tuple_element"> { - let description = [{ - Test op that returns a specified element of the tuple. - }]; - - let arguments = (ins - TupleOf<[AnyType]>, - I32Attr:$index - ); - let results = (outs AnyType); -} - -def MakeTupleOp: TEST_Op<"make_tuple"> { - let description = [{ - Test op that creates a tuple value from a list of values. - }]; - - let arguments = (ins - Variadic:$inputs - ); - let results = (outs TupleOf<[AnyType]>); -} - #endif // TEST_OPS diff --git a/mlir/test/lib/Transforms/TestFinalizingBufferize.cpp b/mlir/test/lib/Transforms/TestFinalizingBufferize.cpp --- a/mlir/test/lib/Transforms/TestFinalizingBufferize.cpp +++ b/mlir/test/lib/Transforms/TestFinalizingBufferize.cpp @@ -60,8 +60,6 @@ // Mark all Standard operations legal. target.addLegalDialect(); target.addLegalOp(); - target.addLegalOp(); - target.addLegalOp(); target.addLegalOp(); target.addLegalOp(); @@ -87,35 +85,6 @@ converter.setResultConversionKind( kind); - converter.addDecomposeTypeConversion( - [](TupleType tupleType, SmallVectorImpl &types) { - tupleType.getFlattenedTypes(types); - return success(); - }); - - converter.addArgumentMaterialization( - [](OpBuilder &builder, TupleType resultType, ValueRange inputs, - Location loc) -> Optional { - if (inputs.size() == 1) - return llvm::None; - TypeRange TypeRange = inputs.getTypes(); - SmallVector types(TypeRange.begin(), TypeRange.end()); - TupleType tuple = TupleType::get(types, builder.getContext()); - mlir::Value value = builder.create(loc, tuple, inputs); - return value; - }); - - converter.addDecomposeValueConversion([](OpBuilder &builder, Location loc, - TupleType resultType, Value value, - SmallVectorImpl &values) { - for (unsigned i = 0, e = resultType.size(); i < e; ++i) { - Value res = builder.create( - loc, resultType.getType(i), value, builder.getI32IntegerAttr(i)); - values.push_back(res); - } - return success(); - }); - OwningRewritePatternList patterns; populateWithBufferizeOpConversionPatterns(