[mlir] LLVM import: handle function-typed constants
authorAlex Zinenko <zinenko@google.com>
Wed, 15 Jan 2020 13:56:25 +0000 (14:56 +0100)
committerAlex Zinenko <zinenko@google.com>
Wed, 15 Jan 2020 14:01:49 +0000 (15:01 +0100)
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
mlir/test/Target/import.ll

index 3bacd0a..90083fb 100644 (file)
@@ -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<llvm::Function>(value))
+    return b.getSymbolRefAttr(f->getName());
   return Attribute();
 }
 
index 1ea7af1..d6bf039 100644 (file)
@@ -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
+}