From dc553ce646cdbab32d72d263d3f289952648b920 Mon Sep 17 00:00:00 2001 From: Alex Zinenko Date: Wed, 15 Jan 2020 14:56:25 +0100 Subject: [PATCH] [mlir] LLVM import: handle function-typed constants The current implementation of the LLVM-to-MLIR translation could not handle functions used as constant values in instructions. The handling is added trivially as `llvm.mlir.constant` can define constants of function type using SymbolRef attributes, which works even for functions that have not been declared yet. --- mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp | 2 ++ mlir/test/Target/import.ll | 38 +++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp index 3bacd0a..90083fb 100644 --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -209,6 +209,8 @@ Attribute Importer::getConstantAsAttr(llvm::Constant *value) { else if (c->getType()->isFloatingPointTy()) return b.getFloatAttr(FloatType::getF32(context), c->getValueAPF()); } + if (auto *f = dyn_cast(value)) + return b.getSymbolRefAttr(f->getName()); return Attribute(); } diff --git a/mlir/test/Target/import.ll b/mlir/test/Target/import.ll index 1ea7af1..d6bf039 100644 --- a/mlir/test/Target/import.ll +++ b/mlir/test/Target/import.ll @@ -208,4 +208,40 @@ define void @FPArithmetic(float %a, float %b, double %c, double %d) { ; CHECK: %[[a13:[0-9]+]] = llvm.frem %arg2, %arg3 : !llvm.double %11 = frem double %c, %d ret void -} \ No newline at end of file +} + +; +; Functions as constants. +; + +; Calling the function that has not been defined yet. +; CHECK-LABEL: @precaller +define i32 @precaller() { + %1 = alloca i32 ()* + ; CHECK: %[[func:.*]] = llvm.mlir.constant(@callee) : !llvm<"i32 ()*"> + ; CHECK: llvm.store %[[func]], %[[loc:.*]] + store i32 ()* @callee, i32 ()** %1 + ; CHECK: %[[indir:.*]] = llvm.load %[[loc]] + %2 = load i32 ()*, i32 ()** %1 + ; CHECK: llvm.call %[[indir]]() + %3 = call i32 %2() + ret i32 %3 +} + +define i32 @callee() { + ret i32 42 +} + +; Calling the function that has been defined. +; CHECK-LABEL: @postcaller +define i32 @postcaller() { + %1 = alloca i32 ()* + ; CHECK: %[[func:.*]] = llvm.mlir.constant(@callee) : !llvm<"i32 ()*"> + ; CHECK: llvm.store %[[func]], %[[loc:.*]] + store i32 ()* @callee, i32 ()** %1 + ; CHECK: %[[indir:.*]] = llvm.load %[[loc]] + %2 = load i32 ()*, i32 ()** %1 + ; CHECK: llvm.call %[[indir]]() + %3 = call i32 %2() + ret i32 %3 +} -- 2.7.4