Skip to content

Commit 829a6ca

Browse files
committed
[MLIR][LLVM] Don't use void return type in MLIR APIs.
In the LLVM IR dialect, `LLVMVoidType` is used to model the return type of LLVM IR functions with no return value. This is inconsistent with MLIR APIs, which expect a function with no return value to have an empty return type. Handle this special case in `LLVMFuncOp` to avoid mismatches between the number of return values and return types between caller and callee. The parser of `LLVMFuncOp` is adapted to be symmetric with the printer, and not allow `!llvm.void` to be expressed explicitly as a return type in the IR, thus avoiding to expose this implementation detail. Differential Revision: https://reviews.llvm.org/D141676
1 parent 2004ab4 commit 829a6ca

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,14 +1514,18 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
15141514
ArrayRef<Type> getArgumentTypes() { return getFunctionType().getParams(); }
15151515

15161516
/// Returns the result types of this function.
1517-
ArrayRef<Type> getResultTypes() { return getFunctionType().getReturnTypes(); }
1517+
ArrayRef<Type> getResultTypes() {
1518+
if (getFunctionType().getReturnType().isa<LLVM::LLVMVoidType>())
1519+
return {};
1520+
return getFunctionType().getReturnTypes();
1521+
}
15181522

15191523
/// Returns the callable region, which is the function body. If the function
15201524
/// is external, returns null.
15211525
Region *getCallableRegion();
15221526

15231527
/// Returns the callable result type, which is the function return type.
1524-
ArrayRef<Type> getCallableResults() { return getFunctionType().getReturnTypes(); }
1528+
ArrayRef<Type> getCallableResults() { return getResultTypes(); }
15251529

15261530
}];
15271531

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2044,7 +2044,16 @@ buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef<Type> inputs,
20442044
llvmInputs.push_back(t);
20452045
}
20462046

2047-
// No output is denoted as "void" in LLVM type system.
2047+
// The void return type is an internal implementation detail that should not
2048+
// be expressed explicitly on the IR. This is symmetric to the printer, which
2049+
// does not print the implicit void return type.
2050+
if (!outputs.empty() && outputs.front().isa<LLVMVoidType>()) {
2051+
parser.emitError(loc, "failed to construct function type: void return type "
2052+
"should not be passed explicitly");
2053+
return {};
2054+
}
2055+
2056+
// Set implicit void type to represent no return value.
20482057
Type llvmOutput =
20492058
outputs.empty() ? LLVMVoidType::get(b.getContext()) : outputs.front();
20502059
if (!isCompatibleType(llvmOutput)) {

mlir/test/Dialect/LLVMIR/func.mlir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ module {
256256
// -----
257257

258258
module {
259-
// expected-error@+1 {{cannot attach result attributes to functions with a void return}}
260-
llvm.func @variadic_def() -> (!llvm.void {llvm.noundef})
259+
// expected-error@+1 {{void return type should not be passed explicitly}}
260+
llvm.func @variadic_def() -> (!llvm.void)
261261
}
262262

263263
// -----

mlir/test/Target/LLVMIR/llvmir-types.mlir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//
66

77
// CHECK: declare void @return_void()
8-
llvm.func @return_void() -> !llvm.void
8+
llvm.func @return_void()
99
// CHECK: declare half @return_half()
1010
llvm.func @return_half() -> f16
1111
// CHECK: declare bfloat @return_bfloat()
@@ -28,7 +28,7 @@ llvm.func @return_x86_mmx() -> !llvm.x86_mmx
2828
//
2929

3030
// CHECK: declare void @f_void_i32(i32)
31-
llvm.func @f_void_i32(i32) -> !llvm.void
31+
llvm.func @f_void_i32(i32)
3232
// CHECK: declare i32 @f_i32_empty()
3333
llvm.func @f_i32_empty() -> i32
3434
// CHECK: declare i32 @f_i32_half_bfloat_float_double(half, bfloat, float, double)

0 commit comments

Comments
 (0)