diff --git a/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h b/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h --- a/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h +++ b/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h @@ -25,6 +25,8 @@ namespace LLVM { class LLVMDialect; class LLVMPointerType; +class LLVMFunctionType; +class LLVMStructType; } // namespace LLVM /// Conversion from types to the LLVM IR dialect. @@ -106,7 +108,8 @@ /// pointers to memref descriptors for arguments. Also converts the return /// type to a pointer argument if it is a struct. Returns true if this /// was the case. - std::pair convertFunctionTypeCWrapper(FunctionType type); + std::pair + convertFunctionTypeCWrapper(FunctionType type); /// Returns the data layout to use during and after conversion. const llvm::DataLayout &getDataLayout() { return options.dataLayout; } diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td --- a/mlir/include/mlir/Conversion/Passes.td +++ b/mlir/include/mlir/Conversion/Passes.td @@ -311,7 +311,10 @@ Option<"dataLayout", "data-layout", "std::string", /*default=*/"\"\"", "String description (LLVM format) of the data layout that is " - "expected on the produced module"> + "expected on the produced module">, + Option<"useOpaquePointers", "use-opaque-pointers", "bool", + /*default=*/"false", "Generate LLVM IR using opaque pointers " + "instead of typed pointers">, ]; } diff --git a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp --- a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp +++ b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp @@ -113,16 +113,17 @@ func::FuncOp funcOp, LLVM::LLVMFuncOp newFuncOp) { auto type = funcOp.getFunctionType(); - auto [wrapperFuncType, resultIsNowArg] = + auto [wrapperFuncType, resultStructType] = typeConverter.convertFunctionTypeCWrapper(type); SmallVector attributes; // Only modify the argument and result attributes when the result is now an // argument. - if (resultIsNowArg) + if (resultStructType) prependEmptyArgAttr(rewriter, attributes, funcOp); - filterFuncAttributes(funcOp, /*filterArgAndResAttrs=*/resultIsNowArg, - attributes); + filterFuncAttributes( + funcOp, /*filterArgAndResAttrs=*/static_cast(resultStructType), + attributes); auto wrapperFuncOp = rewriter.create( loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(), wrapperFuncType, LLVM::Linkage::External, /*dsoLocal*/ false, @@ -132,16 +133,18 @@ rewriter.setInsertionPointToStart(wrapperFuncOp.addEntryBlock()); SmallVector args; - size_t argOffset = resultIsNowArg ? 1 : 0; - for (auto &en : llvm::enumerate(type.getInputs())) { - Value arg = wrapperFuncOp.getArgument(en.index() + argOffset); - if (auto memrefType = en.value().dyn_cast()) { - Value loaded = rewriter.create(loc, arg); + size_t argOffset = resultStructType ? 1 : 0; + for (auto &[index, argType] : llvm::enumerate(type.getInputs())) { + Value arg = wrapperFuncOp.getArgument(index + argOffset); + if (auto memrefType = argType.dyn_cast()) { + Value loaded = rewriter.create( + loc, typeConverter.convertType(memrefType), arg); MemRefDescriptor::unpack(rewriter, loc, loaded, memrefType, args); continue; } - if (en.value().isa()) { - Value loaded = rewriter.create(loc, arg); + if (argType.isa()) { + Value loaded = rewriter.create( + loc, typeConverter.convertType(argType), arg); UnrankedMemRefDescriptor::unpack(rewriter, loc, loaded, args); continue; } @@ -151,7 +154,7 @@ auto call = rewriter.create(loc, newFuncOp, args); - if (resultIsNowArg) { + if (resultStructType) { rewriter.create(loc, call.getResult(), wrapperFuncOp.getArgument(0)); rewriter.create(loc, ValueRange{}); @@ -175,7 +178,7 @@ LLVM::LLVMFuncOp newFuncOp) { OpBuilder::InsertionGuard guard(builder); - auto [wrapperType, resultIsNowArg] = + auto [wrapperType, resultStructType] = typeConverter.convertFunctionTypeCWrapper(funcOp.getFunctionType()); // This conversion can only fail if it could not convert one of the argument // types. But since it has been applied to a non-wrapper function before, it @@ -185,10 +188,11 @@ SmallVector attributes; // Only modify the argument and result attributes when the result is now an // argument. - if (resultIsNowArg) + if (resultStructType) prependEmptyArgAttr(builder, attributes, funcOp); - filterFuncAttributes(funcOp, /*filterArgAndResAttrs=*/resultIsNowArg, - attributes); + filterFuncAttributes( + funcOp, /*filterArgAndResAttrs=*/static_cast(resultStructType), + attributes); // Create the auxiliary function. auto wrapperFunc = builder.create( @@ -204,14 +208,15 @@ args.reserve(type.getNumInputs()); ValueRange wrapperArgsRange(newFuncOp.getArguments()); - if (resultIsNowArg) { + if (resultStructType) { // Allocate the struct on the stack and pass the pointer. Type resultType = wrapperType.cast().getParamType(0); Value one = builder.create( loc, typeConverter.convertType(builder.getIndexType()), builder.getIntegerAttr(builder.getIndexType(), 1)); - Value result = builder.create(loc, resultType, one); + Value result = + builder.create(loc, resultType, resultStructType, one); args.push_back(result); } @@ -234,12 +239,12 @@ builder, loc, typeConverter, unrankedMemRefType, wrapperArgsRange.take_front(numToDrop)); - auto ptrTy = LLVM::LLVMPointerType::get(packed.getType()); + auto ptrTy = typeConverter.getPointerType(packed.getType()); Value one = builder.create( loc, typeConverter.convertType(builder.getIndexType()), builder.getIntegerAttr(builder.getIndexType(), 1)); - Value allocated = - builder.create(loc, ptrTy, one, /*alignment=*/0); + Value allocated = builder.create( + loc, ptrTy, packed.getType(), one, /*alignment=*/0); builder.create(loc, packed, allocated); arg = allocated; } else { @@ -253,8 +258,9 @@ auto call = builder.create(loc, wrapperFunc, args); - if (resultIsNowArg) { - Value result = builder.create(loc, args.front()); + if (resultStructType) { + Value result = + builder.create(loc, resultStructType, args.front()); builder.create(loc, result); } else { builder.create(loc, call.getResults()); @@ -734,6 +740,7 @@ if (indexBitwidth != kDeriveIndexBitwidthFromDataLayout) options.overrideIndexBitwidth(indexBitwidth); options.dataLayout = llvm::DataLayout(this->dataLayout); + options.useOpaquePointers = useOpaquePointers; LLVMTypeConverter typeConverter(&getContext(), options, &dataLayoutAnalysis); diff --git a/mlir/lib/Conversion/LLVMCommon/Pattern.cpp b/mlir/lib/Conversion/LLVMCommon/Pattern.cpp --- a/mlir/lib/Conversion/LLVMCommon/Pattern.cpp +++ b/mlir/lib/Conversion/LLVMCommon/Pattern.cpp @@ -276,7 +276,8 @@ ? builder.create(loc, mallocFunc, allocationSize) .getResult() : builder.create(loc, getVoidPtrType(), - getVoidType(), allocationSize, + IntegerType::get(getContext(), 8), + allocationSize, /*alignment=*/0); Value source = desc.memRefDescPtr(builder, loc); builder.create(loc, memory, source, allocationSize, zero); diff --git a/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp b/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp --- a/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp +++ b/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp @@ -245,10 +245,9 @@ /// Converts the function type to a C-compatible format, in particular using /// pointers to memref descriptors for arguments. -std::pair +std::pair LLVMTypeConverter::convertFunctionTypeCWrapper(FunctionType type) { SmallVector inputs; - bool resultIsNowArg = false; Type resultType = type.getNumResults() == 0 ? LLVM::LLVMVoidType::get(&getContext()) @@ -256,12 +255,12 @@ if (!resultType) return {}; - if (auto structType = resultType.dyn_cast()) { + auto structType = resultType.dyn_cast(); + if (structType) { // Struct types cannot be safely returned via C interface. Make this a // pointer argument, instead. - inputs.push_back(LLVM::LLVMPointerType::get(structType)); + inputs.push_back(getPointerType(structType)); resultType = LLVM::LLVMVoidType::get(&getContext()); - resultIsNowArg = true; } for (Type t : type.getInputs()) { @@ -269,11 +268,11 @@ if (!converted || !LLVM::isCompatibleType(converted)) return {}; if (t.isa()) - converted = LLVM::LLVMPointerType::get(converted); + converted = getPointerType(converted); inputs.push_back(converted); } - return {LLVM::LLVMFunctionType::get(resultType, inputs), resultIsNowArg}; + return {LLVM::LLVMFunctionType::get(resultType, inputs), structType}; } /// Convert a memref type into a list of LLVM IR types that will form the diff --git a/mlir/test/Conversion/FuncToLLVM/calling-convention.mlir b/mlir/test/Conversion/FuncToLLVM/calling-convention.mlir --- a/mlir/test/Conversion/FuncToLLVM/calling-convention.mlir +++ b/mlir/test/Conversion/FuncToLLVM/calling-convention.mlir @@ -1,5 +1,5 @@ -// RUN: mlir-opt -finalize-memref-to-llvm -llvm-request-c-wrappers -convert-func-to-llvm -reconcile-unrealized-casts %s | FileCheck %s -// RUN: mlir-opt -finalize-memref-to-llvm -convert-func-to-llvm -reconcile-unrealized-casts %s | FileCheck %s --check-prefix=EMIT_C_ATTRIBUTE +// RUN: mlir-opt -finalize-memref-to-llvm='use-opaque-pointers=1' -llvm-request-c-wrappers -convert-func-to-llvm='use-opaque-pointers=1' -reconcile-unrealized-casts %s | FileCheck %s +// RUN: mlir-opt -finalize-memref-to-llvm='use-opaque-pointers=1' -convert-func-to-llvm='use-opaque-pointers=1' -reconcile-unrealized-casts %s | FileCheck %s --check-prefix=EMIT_C_ATTRIBUTE // This tests the default memref calling convention and the emission of C // wrappers. We don't need to separate runs because the wrapper-emission @@ -8,11 +8,11 @@ // An external function is transformed into the glue around calling an interface function. // CHECK-LABEL: @external -// CHECK: %[[ALLOC0:.*]]: !llvm.ptr, %[[ALIGN0:.*]]: !llvm.ptr, %[[OFFSET0:.*]]: i64, %[[SIZE00:.*]]: i64, %[[SIZE01:.*]]: i64, %[[STRIDE00:.*]]: i64, %[[STRIDE01:.*]]: i64, -// CHECK: %[[ALLOC1:.*]]: !llvm.ptr, %[[ALIGN1:.*]]: !llvm.ptr, %[[OFFSET1:.*]]: i64) +// CHECK: %[[ALLOC0:.*]]: !llvm.ptr, %[[ALIGN0:.*]]: !llvm.ptr, %[[OFFSET0:.*]]: i64, %[[SIZE00:.*]]: i64, %[[SIZE01:.*]]: i64, %[[STRIDE00:.*]]: i64, %[[STRIDE01:.*]]: i64, +// CHECK: %[[ALLOC1:.*]]: !llvm.ptr, %[[ALIGN1:.*]]: !llvm.ptr, %[[OFFSET1:.*]]: i64) func.func private @external(%arg0: memref, %arg1: memref) // Populate the descriptor for arg0. - // CHECK: %[[DESC00:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> + // CHECK: %[[DESC00:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC01:.*]] = llvm.insertvalue %arg0, %[[DESC00]][0] // CHECK: %[[DESC02:.*]] = llvm.insertvalue %arg1, %[[DESC01]][1] // CHECK: %[[DESC03:.*]] = llvm.insertvalue %arg2, %[[DESC02]][2] @@ -23,18 +23,18 @@ // Allocate on stack and store to comply with C calling convention. // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : index) - // CHECK: %[[DESC0_ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> + // CHECK: %[[DESC0_ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.store %[[DESC07]], %[[DESC0_ALLOCA]] // Populate the descriptor for arg1. - // CHECK: %[[DESC10:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64)> - // CHECK: %[[DESC11:.*]] = llvm.insertvalue %arg7, %[[DESC10]][0] : !llvm.struct<(ptr, ptr, i64)> - // CHECK: %[[DESC12:.*]] = llvm.insertvalue %arg8, %[[DESC11]][1] : !llvm.struct<(ptr, ptr, i64)> - // CHECK: %[[DESC13:.*]] = llvm.insertvalue %arg9, %[[DESC12]][2] : !llvm.struct<(ptr, ptr, i64)> + // CHECK: %[[DESC10:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64)> + // CHECK: %[[DESC11:.*]] = llvm.insertvalue %arg7, %[[DESC10]][0] : !llvm.struct<(ptr, ptr, i64)> + // CHECK: %[[DESC12:.*]] = llvm.insertvalue %arg8, %[[DESC11]][1] : !llvm.struct<(ptr, ptr, i64)> + // CHECK: %[[DESC13:.*]] = llvm.insertvalue %arg9, %[[DESC12]][2] : !llvm.struct<(ptr, ptr, i64)> // Allocate on stack and store to comply with C calling convention. // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : index) - // CHECK: %[[DESC1_ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, ptr, i64)> + // CHECK: %[[DESC1_ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, ptr, i64)> // CHECK: llvm.store %[[DESC13]], %[[DESC1_ALLOCA]] // Call the interface function. @@ -42,18 +42,18 @@ // Verify that an interface function is emitted. // CHECK-LABEL: llvm.func @_mlir_ciface_external -// CHECK: (!llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>>, !llvm.ptr, ptr, i64)>>) +// CHECK: (!llvm.ptr, !llvm.ptr) // Verify that the return value is not affected. // CHECK-LABEL: @returner -// CHECK: -> !llvm.struct<(struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>, struct<(ptr, ptr, i64)>)> +// CHECK: -> !llvm.struct<(struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>, struct<(ptr, ptr, i64)>)> func.func private @returner() -> (memref, memref) // CHECK-LABEL: @caller func.func @caller() { %0:2 = call @returner() : () -> (memref, memref) // Extract individual values from the descriptor for the first memref. - // CHECK: %[[ALLOC0:.*]] = llvm.extractvalue %[[DESC0:.*]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> + // CHECK: %[[ALLOC0:.*]] = llvm.extractvalue %[[DESC0:.*]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[ALIGN0:.*]] = llvm.extractvalue %[[DESC0]][1] // CHECK: %[[OFFSET0:.*]] = llvm.extractvalue %[[DESC0]][2] // CHECK: %[[SIZE00:.*]] = llvm.extractvalue %[[DESC0]][3, 0] @@ -62,12 +62,12 @@ // CHECK: %[[STRIDE01:.*]] = llvm.extractvalue %[[DESC0]][4, 1] // Extract individual values from the descriptor for the second memref. - // CHECK: %[[ALLOC1:.*]] = llvm.extractvalue %[[DESC1:.*]][0] : !llvm.struct<(ptr, ptr, i64)> + // CHECK: %[[ALLOC1:.*]] = llvm.extractvalue %[[DESC1:.*]][0] : !llvm.struct<(ptr, ptr, i64)> // CHECK: %[[ALIGN1:.*]] = llvm.extractvalue %[[DESC1]][1] // CHECK: %[[OFFSET1:.*]] = llvm.extractvalue %[[DESC1]][2] // Forward the values to the call. - // CHECK: llvm.call @external(%[[ALLOC0]], %[[ALIGN0]], %[[OFFSET0]], %[[SIZE00]], %[[SIZE01]], %[[STRIDE00]], %[[STRIDE01]], %[[ALLOC1]], %[[ALIGN1]], %[[OFFSET1]]) : (!llvm.ptr, !llvm.ptr, i64, i64, i64, i64, i64, !llvm.ptr, !llvm.ptr, i64) -> () + // CHECK: llvm.call @external(%[[ALLOC0]], %[[ALIGN0]], %[[OFFSET0]], %[[SIZE00]], %[[SIZE01]], %[[STRIDE00]], %[[STRIDE01]], %[[ALLOC1]], %[[ALIGN1]], %[[OFFSET1]]) : (!llvm.ptr, !llvm.ptr, i64, i64, i64, i64, i64, !llvm.ptr, !llvm.ptr, i64) -> () call @external(%0#0, %0#1) : (memref, memref) -> () return } @@ -81,9 +81,9 @@ // Verify that an interface function is emitted. // CHECK-LABEL: @_mlir_ciface_callee -// CHECK: %[[ARG0:.*]]: !llvm.ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>> +// CHECK: %[[ARG0:.*]]: !llvm.ptr // Load the memref descriptor pointer. - // CHECK: %[[DESC:.*]] = llvm.load %[[ARG0]] : !llvm.ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>> + // CHECK: %[[DESC:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // Extract individual components of the descriptor. // CHECK: %[[ALLOC:.*]] = llvm.extractvalue %[[DESC]][0] @@ -93,7 +93,7 @@ // CHECK: %[[STRIDE:.*]] = llvm.extractvalue %[[DESC]][4, 0] // Forward the descriptor components to the call. - // CHECK: llvm.call @callee(%[[ALLOC]], %[[ALIGN]], %[[OFFSET]], %[[SIZE]], %[[STRIDE]], %{{.*}}) : (!llvm.ptr, !llvm.ptr, i64, i64, i64, i64) -> () + // CHECK: llvm.call @callee(%[[ALLOC]], %[[ALIGN]], %[[OFFSET]], %[[SIZE]], %[[STRIDE]], %{{.*}}) : (!llvm.ptr, !llvm.ptr, i64, i64, i64, i64) -> () // EMIT_C_ATTRIBUTE-NOT: @mlir_ciface_callee @@ -126,7 +126,7 @@ // CHECK: %[[IDX_SIZE:.*]] = llvm.mlir.constant // CHECK: %[[DOUBLE_PTR_SIZE:.*]] = llvm.mul %[[TWO]], %[[PTR_SIZE]] - // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[CALL_RES]][0] : !llvm.struct<(i64, ptr)> + // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[CALL_RES]][0] : !llvm.struct<(i64, ptr)> // CHECK: %[[DOUBLE_RANK:.*]] = llvm.mul %[[TWO]], %[[RANK]] // CHECK: %[[DOUBLE_RANK_INC:.*]] = llvm.add %[[DOUBLE_RANK]], %[[ONE]] // CHECK: %[[TABLES_SIZE:.*]] = llvm.mul %[[DOUBLE_RANK_INC]], %[[IDX_SIZE]] @@ -136,8 +136,8 @@ // CHECK: %[[SOURCE:.*]] = llvm.extractvalue %[[CALL_RES]][1] // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[SOURCE]], %[[ALLOC_SIZE]], %[[FALSE]]) // CHECK: llvm.call @free(%[[SOURCE]]) - // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> - // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[CALL_RES]][0] : !llvm.struct<(i64, ptr)> + // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> + // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[CALL_RES]][0] : !llvm.struct<(i64, ptr)> // CHECK: %[[DESC_1:.*]] = llvm.insertvalue %[[RANK]], %[[DESC]][0] // CHECK: llvm.insertvalue %[[ALLOCA]], %[[DESC_1]][1] return @@ -147,11 +147,10 @@ func.func @return_var_memref(%arg0: memref<4x3xf32>) -> memref<*xf32> attributes { llvm.emit_c_interface } { // Match the construction of the unranked descriptor. // CHECK: %[[ALLOCA:.*]] = llvm.alloca - // CHECK: %[[MEMORY:.*]] = llvm.bitcast %[[ALLOCA]] // CHECK: %[[RANK:.*]] = llvm.mlir.constant(2 : index) - // CHECK: %[[DESC_0:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> + // CHECK: %[[DESC_0:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK: %[[DESC_1:.*]] = llvm.insertvalue %[[RANK]], %[[DESC_0]][0] - // CHECK: %[[DESC_2:.*]] = llvm.insertvalue %[[MEMORY]], %[[DESC_1]][1] + // CHECK: %[[DESC_2:.*]] = llvm.insertvalue %[[ALLOCA]], %[[DESC_1]][1] %0 = memref.cast %arg0: memref<4x3xf32> to memref<*xf32> @@ -168,8 +167,8 @@ // CHECK: %[[ALLOC_SIZE:.*]] = llvm.add %[[DOUBLE_PTR_SIZE]], %[[TABLES_SIZE]] // CHECK: %[[FALSE:.*]] = llvm.mlir.constant(false) // CHECK: %[[ALLOCATED:.*]] = llvm.call @malloc(%[[ALLOC_SIZE]]) - // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED]], %[[MEMORY]], %[[ALLOC_SIZE]], %[[FALSE]]) - // CHECK: %[[NEW_DESC:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> + // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED]], %[[ALLOCA]], %[[ALLOC_SIZE]], %[[FALSE]]) + // CHECK: %[[NEW_DESC:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK: %[[NEW_DESC_1:.*]] = llvm.insertvalue %[[RANK]], %[[NEW_DESC]][0] // CHECK: %[[NEW_DESC_2:.*]] = llvm.insertvalue %[[ALLOCATED]], %[[NEW_DESC_1]][1] // CHECK: llvm.return %[[NEW_DESC_2]] @@ -178,7 +177,7 @@ // Check that the result memref is passed as parameter // CHECK-LABEL: @_mlir_ciface_return_var_memref -// CHECK-SAME: (%{{.*}}: !llvm.ptr)>>, %{{.*}}: !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>>) +// CHECK-SAME: (%{{.*}}: !llvm.ptr, %{{.*}}: !llvm.ptr) // CHECK-LABEL: llvm.func @return_two_var_memref_caller func.func @return_two_var_memref_caller(%arg0: memref<4x3xf32>) { @@ -212,10 +211,9 @@ func.func @return_two_var_memref(%arg0: memref<4x3xf32>) -> (memref<*xf32>, memref<*xf32>) attributes { llvm.emit_c_interface } { // Match the construction of the unranked descriptor. // CHECK: %[[ALLOCA:.*]] = llvm.alloca - // CHECK: %[[MEMORY:.*]] = llvm.bitcast %[[ALLOCA]] - // CHECK: %[[DESC_0:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> + // CHECK: %[[DESC_0:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK: %[[DESC_1:.*]] = llvm.insertvalue %{{.*}}, %[[DESC_0]][0] - // CHECK: %[[DESC_2:.*]] = llvm.insertvalue %[[MEMORY]], %[[DESC_1]][1] + // CHECK: %[[DESC_2:.*]] = llvm.insertvalue %[[ALLOCA]], %[[DESC_1]][1] %0 = memref.cast %arg0 : memref<4x3xf32> to memref<*xf32> // Only check that we allocate the memory for each operand of the "return" @@ -223,18 +221,18 @@ // convention requires the caller to free them and the caller cannot know // whether they are the same value or not. // CHECK: %[[ALLOCATED_1:.*]] = llvm.call @malloc(%{{.*}}) - // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED_1]], %[[MEMORY]], %{{.*}}, %[[FALSE:.*]]) + // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED_1]], %[[ALLOCA]], %{{.*}}, %[[FALSE:.*]]) // CHECK: %[[RES_1:.*]] = llvm.mlir.undef // CHECK: %[[RES_11:.*]] = llvm.insertvalue %{{.*}}, %[[RES_1]][0] // CHECK: %[[RES_12:.*]] = llvm.insertvalue %[[ALLOCATED_1]], %[[RES_11]][1] // CHECK: %[[ALLOCATED_2:.*]] = llvm.call @malloc(%{{.*}}) - // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED_2]], %[[MEMORY]], %{{.*}}, %[[FALSE]]) + // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED_2]], %[[ALLOCA]], %{{.*}}, %[[FALSE]]) // CHECK: %[[RES_2:.*]] = llvm.mlir.undef // CHECK: %[[RES_21:.*]] = llvm.insertvalue %{{.*}}, %[[RES_2]][0] // CHECK: %[[RES_22:.*]] = llvm.insertvalue %[[ALLOCATED_2]], %[[RES_21]][1] - // CHECK: %[[RESULTS:.*]] = llvm.mlir.undef : !llvm.struct<(struct<(i64, ptr)>, struct<(i64, ptr)>)> + // CHECK: %[[RESULTS:.*]] = llvm.mlir.undef : !llvm.struct<(struct<(i64, ptr)>, struct<(i64, ptr)>)> // CHECK: %[[RESULTS_1:.*]] = llvm.insertvalue %[[RES_12]], %[[RESULTS]] // CHECK: %[[RESULTS_2:.*]] = llvm.insertvalue %[[RES_22]], %[[RESULTS_1]] // CHECK: llvm.return %[[RESULTS_2]] @@ -243,5 +241,5 @@ // Check that the result memrefs are passed as parameter // CHECK-LABEL: @_mlir_ciface_return_two_var_memref -// CHECK-SAME: (%{{.*}}: !llvm.ptr)>, struct<(i64, ptr)>)>>, -// CHECK-SAME: %{{.*}}: !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>>) +// CHECK-SAME: (%{{.*}}: !llvm.ptr, +// CHECK-SAME: %{{.*}}: !llvm.ptr) diff --git a/mlir/test/Conversion/FuncToLLVM/convert-argattrs.mlir b/mlir/test/Conversion/FuncToLLVM/convert-argattrs.mlir --- a/mlir/test/Conversion/FuncToLLVM/convert-argattrs.mlir +++ b/mlir/test/Conversion/FuncToLLVM/convert-argattrs.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt -convert-func-to-llvm %s | FileCheck %s +// RUN: mlir-opt -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s // CHECK-LABEL: func @check_attributes // CHECK-SAME: {dialect.a = true, dialect.b = 4 : i64} diff --git a/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir b/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir --- a/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir +++ b/mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir @@ -1,5 +1,5 @@ -// RUN: mlir-opt -convert-func-to-llvm %s | FileCheck %s -// RUN-32: mlir-opt -convert-func-to-llvm='data-layout=p:32:32:32' %s | FileCheck %s +// RUN: mlir-opt -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s +// RUN-32: mlir-opt -convert-func-to-llvm='data-layout=p:32:32:32 use-opaque-pointers=1' %s | FileCheck %s // CHECK: module attributes {llvm.data_layout = ""} // CHECK-32: module attributes {llvm.data_layout ="p:32:32:32"} diff --git a/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir b/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir --- a/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir +++ b/mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir @@ -1,39 +1,30 @@ -// RUN: mlir-opt -convert-func-to-llvm -split-input-file -verify-diagnostics %s | FileCheck %s +// RUN: mlir-opt -convert-func-to-llvm='use-opaque-pointers=1' -split-input-file -verify-diagnostics %s | FileCheck %s -//CHECK: llvm.func @second_order_arg(!llvm.ptr>) +//CHECK: llvm.func @second_order_arg(!llvm.ptr) func.func private @second_order_arg(%arg0 : () -> ()) -//CHECK: llvm.func @second_order_result() -> !llvm.ptr> +//CHECK: llvm.func @second_order_result() -> !llvm.ptr func.func private @second_order_result() -> (() -> ()) -//CHECK: llvm.func @second_order_multi_result() -> !llvm.struct<(ptr>, ptr>, ptr>)> +//CHECK: llvm.func @second_order_multi_result() -> !llvm.struct<(ptr, ptr, ptr)> func.func private @second_order_multi_result() -> (() -> (i32), () -> (i64), () -> (f32)) -//CHECK: llvm.func @third_order(!llvm.ptr> (ptr>)>>) -> !llvm.ptr> (ptr>)>> -func.func private @third_order(%arg0 : (() -> ()) -> (() -> ())) -> ((() -> ()) -> (() -> ())) - -//CHECK: llvm.func @fifth_order_left(!llvm.ptr>)>>)>>)>>) -func.func private @fifth_order_left(%arg0: (((() -> ()) -> ()) -> ()) -> ()) - -//CHECK: llvm.func @fifth_order_right(!llvm.ptr> ()>> ()>> ()>>) -func.func private @fifth_order_right(%arg0: () -> (() -> (() -> (() -> ())))) - // Check that memrefs are converted to argument packs if appear as function arguments. -// CHECK: llvm.func @memref_call_conv(!llvm.ptr, !llvm.ptr, i64, i64, i64) +// CHECK: llvm.func @memref_call_conv(!llvm.ptr, !llvm.ptr, i64, i64, i64) func.func private @memref_call_conv(%arg0: memref) // Same in nested functions. -// CHECK: llvm.func @memref_call_conv_nested(!llvm.ptr, ptr, i64, i64, i64)>>) +// CHECK: llvm.func @memref_call_conv_nested(!llvm.ptr) func.func private @memref_call_conv_nested(%arg0: (memref) -> ()) -//CHECK-LABEL: llvm.func @pass_through(%arg0: !llvm.ptr>) -> !llvm.ptr> { +//CHECK-LABEL: llvm.func @pass_through(%arg0: !llvm.ptr) -> !llvm.ptr { func.func @pass_through(%arg0: () -> ()) -> (() -> ()) { -// CHECK-NEXT: llvm.br ^bb1(%arg0 : !llvm.ptr>) +// CHECK-NEXT: llvm.br ^bb1(%arg0 : !llvm.ptr) cf.br ^bb1(%arg0 : () -> ()) -//CHECK-NEXT: ^bb1(%0: !llvm.ptr>): +//CHECK-NEXT: ^bb1(%0: !llvm.ptr): ^bb1(%bbarg: () -> ()): -// CHECK-NEXT: llvm.return %0 : !llvm.ptr> +// CHECK-NEXT: llvm.return %0 : !llvm.ptr return %bbarg : () -> () } @@ -50,17 +41,17 @@ // CHECK-LABEL: llvm.func @indirect_const_call // CHECK-SAME: (%[[ARG0:.*]]: i32) { func.func @indirect_const_call(%arg0: i32) { -// CHECK-NEXT: %[[ADDR:.*]] = llvm.mlir.addressof @body : !llvm.ptr> +// CHECK-NEXT: %[[ADDR:.*]] = llvm.mlir.addressof @body : !llvm.ptr %0 = constant @body : (i32) -> () -// CHECK-NEXT: llvm.call %[[ADDR]](%[[ARG0:.*]]) : !llvm.ptr>, (i32) -> () +// CHECK-NEXT: llvm.call %[[ADDR]](%[[ARG0:.*]]) : !llvm.ptr, (i32) -> () call_indirect %0(%arg0) : (i32) -> () // CHECK-NEXT: llvm.return return } -// CHECK-LABEL: llvm.func @indirect_call(%arg0: !llvm.ptr>, %arg1: f32) -> i32 { +// CHECK-LABEL: llvm.func @indirect_call(%arg0: !llvm.ptr, %arg1: f32) -> i32 { func.func @indirect_call(%arg0: (f32) -> i32, %arg1: f32) -> i32 { -// CHECK-NEXT: %0 = llvm.call %arg0(%arg1) : !llvm.ptr>, (f32) -> i32 +// CHECK-NEXT: %0 = llvm.call %arg0(%arg1) : !llvm.ptr, (f32) -> i32 %0 = call_indirect %arg0(%arg1) : (f32) -> i32 // CHECK-NEXT: llvm.return %0 : i32 return %0 : i32 diff --git a/mlir/test/Conversion/FuncToLLVM/convert-types.mlir b/mlir/test/Conversion/FuncToLLVM/convert-types-typed-pointers.mlir rename from mlir/test/Conversion/FuncToLLVM/convert-types.mlir rename to mlir/test/Conversion/FuncToLLVM/convert-types-typed-pointers.mlir diff --git a/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-callers.mlir b/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-callers.mlir --- a/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-callers.mlir +++ b/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-callers.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt -llvm-request-c-wrappers -convert-func-to-llvm %s | FileCheck %s +// RUN: mlir-opt -llvm-request-c-wrappers -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s // CHECK: llvm.func @res_attrs_with_memref_return() -> (!llvm.struct{{.*}} {test.returnOne}) // CHECK-LABEL: llvm.func @_mlir_ciface_res_attrs_with_memref_return diff --git a/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-functions.mlir b/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-functions.mlir --- a/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-functions.mlir +++ b/mlir/test/Conversion/FuncToLLVM/emit-c-wrappers-for-external-functions.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt -llvm-request-c-wrappers -convert-func-to-llvm %s | FileCheck %s +// RUN: mlir-opt -llvm-request-c-wrappers -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s // CHECK: llvm.func @res_attrs_with_memref_return() -> (!llvm.struct{{.*}} {test.returnOne}) // CHECK-LABEL: llvm.func @_mlir_ciface_res_attrs_with_memref_return diff --git a/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir b/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir --- a/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir +++ b/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir @@ -1,89 +1,89 @@ -// RUN: mlir-opt -convert-func-to-llvm -reconcile-unrealized-casts %s | FileCheck %s -// RUN: mlir-opt -convert-func-to-llvm='use-bare-ptr-memref-call-conv=1' -split-input-file %s | FileCheck %s --check-prefix=BAREPTR +// RUN: mlir-opt -convert-func-to-llvm='use-opaque-pointers=1' -reconcile-unrealized-casts %s | FileCheck %s +// RUN: mlir-opt -convert-func-to-llvm='use-bare-ptr-memref-call-conv=1 use-opaque-pointers=1' -split-input-file %s | FileCheck %s --check-prefix=BAREPTR // These tests were separated from func-memref.mlir because applying // -reconcile-unrealized-casts resulted in `llvm.extractvalue` ops getting // folded away. // CHECK-LABEL: func @check_static_return -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 -// CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-LABEL: func @check_static_return -// BAREPTR-SAME: (%[[arg:.*]]: !llvm.ptr) -> !llvm.ptr { +// BAREPTR-SAME: (%[[arg:.*]]: !llvm.ptr) -> !llvm.ptr { func.func @check_static_return(%static : memref<32x18xf32>) -> memref<32x18xf32> { -// CHECK: llvm.return %{{.*}} : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// CHECK: llvm.return %{{.*}} : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR: %[[udf:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: %[[base0:.*]] = llvm.insertvalue %[[arg]], %[[udf]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: %[[aligned:.*]] = llvm.insertvalue %[[arg]], %[[base0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR: %[[udf:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[base0:.*]] = llvm.insertvalue %[[arg]], %[[udf]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[aligned:.*]] = llvm.insertvalue %[[arg]], %[[base0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val0:.*]] = llvm.mlir.constant(0 : index) : i64 -// BAREPTR-NEXT: %[[ins0:.*]] = llvm.insertvalue %[[val0]], %[[aligned]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins0:.*]] = llvm.insertvalue %[[val0]], %[[aligned]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val1:.*]] = llvm.mlir.constant(32 : index) : i64 -// BAREPTR-NEXT: %[[ins1:.*]] = llvm.insertvalue %[[val1]], %[[ins0]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins1:.*]] = llvm.insertvalue %[[val1]], %[[ins0]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val2:.*]] = llvm.mlir.constant(18 : index) : i64 -// BAREPTR-NEXT: %[[ins2:.*]] = llvm.insertvalue %[[val2]], %[[ins1]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins2:.*]] = llvm.insertvalue %[[val2]], %[[ins1]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val3:.*]] = llvm.mlir.constant(18 : index) : i64 -// BAREPTR-NEXT: %[[ins3:.*]] = llvm.insertvalue %[[val3]], %[[ins2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins3:.*]] = llvm.insertvalue %[[val3]], %[[ins2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val4:.*]] = llvm.mlir.constant(1 : index) : i64 -// BAREPTR-NEXT: %[[ins4:.*]] = llvm.insertvalue %[[val4]], %[[ins3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: %[[base1:.*]] = llvm.extractvalue %[[ins4]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: llvm.return %[[base1]] : !llvm.ptr +// BAREPTR-NEXT: %[[ins4:.*]] = llvm.insertvalue %[[val4]], %[[ins3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[base1:.*]] = llvm.extractvalue %[[ins4]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: llvm.return %[[base1]] : !llvm.ptr return %static : memref<32x18xf32> } // ----- // CHECK-LABEL: func @check_static_return_with_offset -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 -// CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-LABEL: func @check_static_return_with_offset -// BAREPTR-SAME: (%[[arg:.*]]: !llvm.ptr) -> !llvm.ptr { +// BAREPTR-SAME: (%[[arg:.*]]: !llvm.ptr) -> !llvm.ptr { func.func @check_static_return_with_offset(%static : memref<32x18xf32, strided<[22,1], offset: 7>>) -> memref<32x18xf32, strided<[22,1], offset: 7>> { -// CHECK: llvm.return %{{.*}} : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// CHECK: llvm.return %{{.*}} : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR: %[[udf:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: %[[base0:.*]] = llvm.insertvalue %[[arg]], %[[udf]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: %[[aligned:.*]] = llvm.insertvalue %[[arg]], %[[base0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR: %[[udf:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[base0:.*]] = llvm.insertvalue %[[arg]], %[[udf]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[aligned:.*]] = llvm.insertvalue %[[arg]], %[[base0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val0:.*]] = llvm.mlir.constant(7 : index) : i64 -// BAREPTR-NEXT: %[[ins0:.*]] = llvm.insertvalue %[[val0]], %[[aligned]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins0:.*]] = llvm.insertvalue %[[val0]], %[[aligned]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val1:.*]] = llvm.mlir.constant(32 : index) : i64 -// BAREPTR-NEXT: %[[ins1:.*]] = llvm.insertvalue %[[val1]], %[[ins0]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins1:.*]] = llvm.insertvalue %[[val1]], %[[ins0]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val2:.*]] = llvm.mlir.constant(22 : index) : i64 -// BAREPTR-NEXT: %[[ins2:.*]] = llvm.insertvalue %[[val2]], %[[ins1]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins2:.*]] = llvm.insertvalue %[[val2]], %[[ins1]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val3:.*]] = llvm.mlir.constant(18 : index) : i64 -// BAREPTR-NEXT: %[[ins3:.*]] = llvm.insertvalue %[[val3]], %[[ins2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[ins3:.*]] = llvm.insertvalue %[[val3]], %[[ins2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val4:.*]] = llvm.mlir.constant(1 : index) : i64 -// BAREPTR-NEXT: %[[ins4:.*]] = llvm.insertvalue %[[val4]], %[[ins3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: %[[base1:.*]] = llvm.extractvalue %[[ins4]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> -// BAREPTR-NEXT: llvm.return %[[base1]] : !llvm.ptr +// BAREPTR-NEXT: %[[ins4:.*]] = llvm.insertvalue %[[val4]], %[[ins3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: %[[base1:.*]] = llvm.extractvalue %[[ins4]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> +// BAREPTR-NEXT: llvm.return %[[base1]] : !llvm.ptr return %static : memref<32x18xf32, strided<[22,1], offset: 7>> } // ----- -// BAREPTR: llvm.func @foo(!llvm.ptr) -> !llvm.ptr +// BAREPTR: llvm.func @foo(!llvm.ptr) -> !llvm.ptr func.func private @foo(memref<10xi8>) -> memref<20xi8> // BAREPTR-LABEL: func @check_memref_func_call -// BAREPTR-SAME: %[[in:.*]]: !llvm.ptr) -> !llvm.ptr +// BAREPTR-SAME: %[[in:.*]]: !llvm.ptr) -> !llvm.ptr func.func @check_memref_func_call(%in : memref<10xi8>) -> memref<20xi8> { // BAREPTR: %[[inDesc:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] - // BAREPTR-NEXT: %[[barePtr:.*]] = llvm.extractvalue %[[inDesc]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> - // BAREPTR-NEXT: %[[call:.*]] = llvm.call @foo(%[[barePtr]]) : (!llvm.ptr) -> !llvm.ptr - // BAREPTR-NEXT: %[[desc0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> - // BAREPTR-NEXT: %[[desc1:.*]] = llvm.insertvalue %[[call]], %[[desc0]][0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> - // BAREPTR-NEXT: %[[desc2:.*]] = llvm.insertvalue %[[call]], %[[desc1]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: %[[barePtr:.*]] = llvm.extractvalue %[[inDesc]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: %[[call:.*]] = llvm.call @foo(%[[barePtr]]) : (!llvm.ptr) -> !llvm.ptr + // BAREPTR-NEXT: %[[desc0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: %[[desc1:.*]] = llvm.insertvalue %[[call]], %[[desc0]][0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: %[[desc2:.*]] = llvm.insertvalue %[[call]], %[[desc1]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : i64 - // BAREPTR-NEXT: %[[desc4:.*]] = llvm.insertvalue %[[c0]], %[[desc2]][2] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: %[[desc4:.*]] = llvm.insertvalue %[[c0]], %[[desc2]][2] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[c20:.*]] = llvm.mlir.constant(20 : index) : i64 - // BAREPTR-NEXT: %[[desc6:.*]] = llvm.insertvalue %[[c20]], %[[desc4]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: %[[desc6:.*]] = llvm.insertvalue %[[c20]], %[[desc4]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[c1:.*]] = llvm.mlir.constant(1 : index) : i64 - // BAREPTR-NEXT: %[[outDesc:.*]] = llvm.insertvalue %[[c1]], %[[desc6]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: %[[outDesc:.*]] = llvm.insertvalue %[[c1]], %[[desc6]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> %res = call @foo(%in) : (memref<10xi8>) -> (memref<20xi8>) - // BAREPTR-NEXT: %[[res:.*]] = llvm.extractvalue %[[outDesc]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> - // BAREPTR-NEXT: llvm.return %[[res]] : !llvm.ptr + // BAREPTR-NEXT: %[[res:.*]] = llvm.extractvalue %[[outDesc]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR-NEXT: llvm.return %[[res]] : !llvm.ptr return %res : memref<20xi8> } @@ -92,6 +92,6 @@ // BAREPTR-LABEL: func @check_return( // BAREPTR-SAME: %{{.*}}: memref) -> memref func.func @check_return(%in : memref) -> memref { - // BAREPTR: llvm.return {{.*}} : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // BAREPTR: llvm.return {{.*}} : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> return %in : memref } diff --git a/mlir/test/Conversion/FuncToLLVM/func-memref.mlir b/mlir/test/Conversion/FuncToLLVM/func-memref.mlir --- a/mlir/test/Conversion/FuncToLLVM/func-memref.mlir +++ b/mlir/test/Conversion/FuncToLLVM/func-memref.mlir @@ -1,8 +1,8 @@ -// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm),convert-func-to-llvm,reconcile-unrealized-casts)" -split-input-file %s | FileCheck %s -// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm),convert-func-to-llvm{use-bare-ptr-memref-call-conv=1},reconcile-unrealized-casts)" -split-input-file %s | FileCheck %s --check-prefix=BAREPTR +// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm),convert-func-to-llvm{use-opaque-pointers=1},reconcile-unrealized-casts)" -split-input-file %s | FileCheck %s +// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm),convert-func-to-llvm{use-bare-ptr-memref-call-conv=1 use-opaque-pointers=1},reconcile-unrealized-casts)" -split-input-file %s | FileCheck %s --check-prefix=BAREPTR // BAREPTR-LABEL: func @check_noalias -// BAREPTR-SAME: %{{.*}}: !llvm.ptr {llvm.noalias}, %{{.*}}: !llvm.ptr {llvm.noalias} +// BAREPTR-SAME: %{{.*}}: !llvm.ptr {llvm.noalias}, %{{.*}}: !llvm.ptr {llvm.noalias} func.func @check_noalias(%static : memref<2xf32> {llvm.noalias}, %other : memref<2xf32> {llvm.noalias}) { return } @@ -10,11 +10,11 @@ // ----- // CHECK-LABEL: func @check_strided_memref_arguments( -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 func.func @check_strided_memref_arguments(%static: memref<10x20xf32, affine_map<(i,j)->(20 * i + j + 1)>>, %dynamic : memref(M * i + j + 1)>>, @@ -25,13 +25,13 @@ // ----- // CHECK-LABEL: func @memref_index -// CHECK-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, +// CHECK-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, // CHECK-SAME: %arg2: i64, %arg3: i64, %arg4: i64) -// CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> +// CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK32-LABEL: func @memref_index -// CHECK32-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, +// CHECK32-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, // CHECK32-SAME: %arg2: i32, %arg3: i32, %arg4: i32) -// CHECK32-SAME: -> !llvm.struct<(ptr, ptr, i32, array<1 x i32>, array<1 x i32>)> +// CHECK32-SAME: -> !llvm.struct<(ptr, ptr, i32, array<1 x i32>, array<1 x i32>)> func.func @memref_index(%arg0: memref<32xindex>) -> memref<32xindex> { return %arg0 : memref<32xindex> } @@ -39,11 +39,11 @@ // ----- // CHECK-LABEL: func @check_arguments -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 -// CHECK-COUNT-2: !llvm.ptr +// CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: i64 func.func @check_arguments(%static: memref<10x20xf32>, %dynamic : memref, %mixed : memref<10x?xf32>) { return @@ -108,7 +108,7 @@ func.func @loop_carried(%arg0 : index, %arg1 : index, %arg2 : index, %base0 : !base_type, %base1 : !base_type) -> (!base_type, !base_type) { // This test checks that in the BAREPTR case, the branch arguments only forward the descriptor. // This test was lowered from a simple scf.for that swaps 2 memref iter_args. - // BAREPTR: llvm.br ^bb1(%{{.*}}, %{{.*}}, %{{.*}} : i64, !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>, !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>) + // BAREPTR: llvm.br ^bb1(%{{.*}}, %{{.*}}, %{{.*}} : i64, !llvm.struct<(ptr<201>, ptr<201>, i64, array<1 x i64>, array<1 x i64>)>, !llvm.struct<(ptr<201>, ptr<201>, i64, array<1 x i64>, array<1 x i64>)>) cf.br ^bb1(%arg0, %base0, %base1 : index, memref<64xi32, 201>, memref<64xi32, 201>) // BAREPTR-NEXT: ^bb1 diff --git a/mlir/test/Conversion/FuncToLLVM/func-to-llvm.mlir b/mlir/test/Conversion/FuncToLLVM/func-to-llvm.mlir --- a/mlir/test/Conversion/FuncToLLVM/func-to-llvm.mlir +++ b/mlir/test/Conversion/FuncToLLVM/func-to-llvm.mlir @@ -1,5 +1,5 @@ -// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-math-to-llvm,convert-arith-to-llvm),convert-func-to-llvm,reconcile-unrealized-casts)" %s -split-input-file | FileCheck %s -// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-math-to-llvm,convert-arith-to-llvm{index-bitwidth=32}),convert-func-to-llvm{index-bitwidth=32},reconcile-unrealized-casts)" %s -split-input-file | FileCheck --check-prefix=CHECK32 %s +// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-math-to-llvm,convert-arith-to-llvm),convert-func-to-llvm{use-opaque-pointers=1},reconcile-unrealized-casts)" %s -split-input-file | FileCheck %s +// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-math-to-llvm,convert-arith-to-llvm{index-bitwidth=32}),convert-func-to-llvm{index-bitwidth=32 use-opaque-pointers=1},reconcile-unrealized-casts)" %s -split-input-file | FileCheck --check-prefix=CHECK32 %s // CHECK-LABEL: func @empty() { // CHECK-NEXT: llvm.return @@ -373,33 +373,33 @@ func.func private @get_c32() -> (complex) // CHECK-LABEL: llvm.func @get_c64() -> !llvm.struct<(f64, f64)> func.func private @get_c64() -> (complex) -// CHECK-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> -// CHECK32-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)> +// CHECK-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> +// CHECK32-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)> func.func private @get_memref() -> (memref<42x?x10x?xf32>) -// CHECK-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> { -// CHECK32-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> { +// CHECK-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> { +// CHECK32-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> { func.func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) { ^bb0: // CHECK-NEXT: {{.*}} = llvm.call @get_i64() : () -> i64 // CHECK-NEXT: {{.*}} = llvm.call @get_f32() : () -> f32 -// CHECK-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> +// CHECK-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> // CHECK32-NEXT: {{.*}} = llvm.call @get_i64() : () -> i64 // CHECK32-NEXT: {{.*}} = llvm.call @get_f32() : () -> f32 -// CHECK32-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)> +// CHECK32-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)> %0 = call @get_i64() : () -> (i64) %1 = call @get_f32() : () -> (f32) %2 = call @get_memref() : () -> (memref<42x?x10x?xf32>) -// CHECK-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK32-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> -// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> -// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> -// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> -// CHECK32-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK32-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK32-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> return %0, %1, %2 : i64, f32, memref<42x?x10x?xf32> } @@ -408,14 +408,14 @@ // CHECK32-LABEL: llvm.func @multireturn_caller() { func.func @multireturn_caller() { ^bb0: -// CHECK-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> -// CHECK32-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> -// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> -// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> -// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK32-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> +// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> %0:3 = call @multireturn() : () -> (i64, f32, memref<42x?x10x?xf32>) %1 = arith.constant 42 : i64 // CHECK: {{.*}} = llvm.add {{.*}}, {{.*}} : i64 diff --git a/mlir/test/Conversion/FuncToLLVM/invalid.mlir b/mlir/test/Conversion/FuncToLLVM/invalid.mlir --- a/mlir/test/Conversion/FuncToLLVM/invalid.mlir +++ b/mlir/test/Conversion/FuncToLLVM/invalid.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -convert-func-to-llvm -verify-diagnostics -split-input-file +// RUN: mlir-opt %s -convert-func-to-llvm='use-opaque-pointers=1' -verify-diagnostics -split-input-file // Should not crash on unsupported types in function signatures. func.func private @unsupported_signature() -> tensor<10 x i32> diff --git a/mlir/test/Conversion/FuncToLLVM/typed-pointers.mlir b/mlir/test/Conversion/FuncToLLVM/typed-pointers.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Conversion/FuncToLLVM/typed-pointers.mlir @@ -0,0 +1,114 @@ +// RUN: mlir-opt -convert-func-to-llvm='use-opaque-pointers=0' -split-input-file %s | FileCheck %s + +//CHECK: llvm.func @second_order_arg(!llvm.ptr>) +func.func private @second_order_arg(%arg0 : () -> ()) + +//CHECK: llvm.func @second_order_result() -> !llvm.ptr> +func.func private @second_order_result() -> (() -> ()) + +//CHECK: llvm.func @second_order_multi_result() -> !llvm.struct<(ptr>, ptr>, ptr>)> +func.func private @second_order_multi_result() -> (() -> (i32), () -> (i64), () -> (f32)) + +//CHECK: llvm.func @third_order(!llvm.ptr> (ptr>)>>) -> !llvm.ptr> (ptr>)>> +func.func private @third_order(%arg0 : (() -> ()) -> (() -> ())) -> ((() -> ()) -> (() -> ())) + +//CHECK: llvm.func @fifth_order_left(!llvm.ptr>)>>)>>)>>) +func.func private @fifth_order_left(%arg0: (((() -> ()) -> ()) -> ()) -> ()) + +//CHECK: llvm.func @fifth_order_right(!llvm.ptr> ()>> ()>> ()>>) +func.func private @fifth_order_right(%arg0: () -> (() -> (() -> (() -> ())))) + +// Check that memrefs are converted to argument packs if appear as function arguments. +// CHECK: llvm.func @memref_call_conv(!llvm.ptr, !llvm.ptr, i64, i64, i64) +func.func private @memref_call_conv(%arg0: memref) + +// Same in nested functions. +// CHECK: llvm.func @memref_call_conv_nested(!llvm.ptr, ptr, i64, i64, i64)>>) +func.func private @memref_call_conv_nested(%arg0: (memref) -> ()) + +//CHECK-LABEL: llvm.func @pass_through(%arg0: !llvm.ptr>) -> !llvm.ptr> { +func.func @pass_through(%arg0: () -> ()) -> (() -> ()) { +// CHECK-NEXT: llvm.br ^bb1(%arg0 : !llvm.ptr>) + cf.br ^bb1(%arg0 : () -> ()) + +//CHECK-NEXT: ^bb1(%0: !llvm.ptr>): +^bb1(%bbarg: () -> ()): +// CHECK-NEXT: llvm.return %0 : !llvm.ptr> + return %bbarg : () -> () +} + +// CHECK-LABEL: llvm.func @indirect_call(%arg0: !llvm.ptr>, %arg1: f32) -> i32 { +func.func @indirect_call(%arg0: (f32) -> i32, %arg1: f32) -> i32 { +// CHECK-NEXT: %0 = llvm.call %arg0(%arg1) : !llvm.ptr>, (f32) -> i32 + %0 = call_indirect %arg0(%arg1) : (f32) -> i32 +// CHECK-NEXT: llvm.return %0 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @get_i64() -> i64 +func.func private @get_i64() -> (i64) +// CHECK-LABEL: llvm.func @get_f32() -> f32 +func.func private @get_f32() -> (f32) +// CHECK-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> +func.func private @get_memref() -> (memref<42x?x10x?xf32>) + +// CHECK-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> { +func.func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) { +^bb0: +// CHECK-NEXT: {{.*}} = llvm.call @get_i64() : () -> i64 +// CHECK-NEXT: {{.*}} = llvm.call @get_f32() : () -> f32 +// CHECK-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> + %0 = call @get_i64() : () -> (i64) + %1 = call @get_f32() : () -> (f32) + %2 = call @get_memref() : () -> (memref<42x?x10x?xf32>) +// CHECK-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> +// CHECK-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> + return %0, %1, %2 : i64, f32, memref<42x?x10x?xf32> +} + +//===========================================================================// +// Calling convention on returning unranked memrefs. +// IR below produced by running -finalize-memref-to-llvm without opaque +// pointers on calling-convention.mlir +//===========================================================================// + +func.func @return_var_memref(%arg0: memref<4x3xf32>) -> memref<*xf32> attributes {llvm.emit_c_interface} { + %0 = builtin.unrealized_conversion_cast %arg0 : memref<4x3xf32> to !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> + %1 = llvm.mlir.constant(1 : index) : i64 + %2 = llvm.alloca %1 x !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> : (i64) -> !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>> + llvm.store %0, %2 : !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>> + %3 = llvm.bitcast %2 : !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>> to !llvm.ptr + %4 = llvm.mlir.constant(2 : index) : i64 + %5 = llvm.mlir.undef : !llvm.struct<(i64, ptr)> + %6 = llvm.insertvalue %4, %5[0] : !llvm.struct<(i64, ptr)> + %7 = llvm.insertvalue %3, %6[1] : !llvm.struct<(i64, ptr)> + %8 = builtin.unrealized_conversion_cast %7 : !llvm.struct<(i64, ptr)> to memref<*xf32> + return %8 : memref<*xf32> +} + +// Check that the result memref is passed as parameter +// CHECK-LABEL: @_mlir_ciface_return_var_memref +// CHECK-SAME: (%{{.*}}: !llvm.ptr)>>, %{{.*}}: !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>>) + +func.func @return_two_var_memref(%arg0: memref<4x3xf32>) -> (memref<*xf32>, memref<*xf32>) attributes {llvm.emit_c_interface} { + %0 = builtin.unrealized_conversion_cast %arg0 : memref<4x3xf32> to !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> + %1 = llvm.mlir.constant(1 : index) : i64 + %2 = llvm.alloca %1 x !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> : (i64) -> !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>> + llvm.store %0, %2 : !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>> + %3 = llvm.bitcast %2 : !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>> to !llvm.ptr + %4 = llvm.mlir.constant(2 : index) : i64 + %5 = llvm.mlir.undef : !llvm.struct<(i64, ptr)> + %6 = llvm.insertvalue %4, %5[0] : !llvm.struct<(i64, ptr)> + %7 = llvm.insertvalue %3, %6[1] : !llvm.struct<(i64, ptr)> + %8 = builtin.unrealized_conversion_cast %7 : !llvm.struct<(i64, ptr)> to memref<*xf32> + return %8, %8 : memref<*xf32>, memref<*xf32> +} + +// Check that the result memrefs are passed as parameter +// CHECK-LABEL: @_mlir_ciface_return_two_var_memref +// CHECK-SAME: (%{{.*}}: !llvm.ptr)>, struct<(i64, ptr)>)>>, +// CHECK-SAME: %{{.*}}: !llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>>) + diff --git a/mlir/test/lib/Conversion/FuncToLLVM/TestConvertCallOp.cpp b/mlir/test/lib/Conversion/FuncToLLVM/TestConvertCallOp.cpp --- a/mlir/test/lib/Conversion/FuncToLLVM/TestConvertCallOp.cpp +++ b/mlir/test/lib/Conversion/FuncToLLVM/TestConvertCallOp.cpp @@ -48,8 +48,11 @@ void runOnOperation() override { ModuleOp m = getOperation(); + LowerToLLVMOptions options(m.getContext()); + options.useOpaquePointers = false; + // Populate type conversions. - LLVMTypeConverter typeConverter(m.getContext()); + LLVMTypeConverter typeConverter(m.getContext(), options); typeConverter.addConversion([&](test::TestType type) { return LLVM::LLVMPointerType::get(IntegerType::get(m.getContext(), 8)); });