Add std.log* and llvm.intr.log* that correspond to the LLVMIR intrinsics
authorNicolas Vasilache <ntv@google.com>
Wed, 11 Dec 2019 23:25:00 +0000 (15:25 -0800)
committerA. Unique TensorFlower <gardener@tensorflow.org>
Wed, 11 Dec 2019 23:25:34 +0000 (15:25 -0800)
PiperOrigin-RevId: 285073483

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/include/mlir/Dialect/StandardOps/Ops.td
mlir/lib/Conversion/StandardToLLVM/ConvertStandardToLLVM.cpp
mlir/test/Target/llvmir-intrinsics.mlir

index 166cc5c..a711914 100644 (file)
@@ -684,4 +684,38 @@ def LLVM_ExpOp : LLVM_Op<"intr.exp", [NoSideEffect]>,
     $res = builder.CreateCall(fn, {$in});
   }];
 }
+
+def LLVM_LogOp : LLVM_Op<"intr.log", [NoSideEffect]>,
+                   Arguments<(ins LLVM_Type:$in)>,
+                   Results<(outs LLVM_Type:$res)> {
+  let llvmBuilder = [{
+    llvm::Module *module = builder.GetInsertBlock()->getModule();
+    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
+        module, llvm::Intrinsic::log, {$in->getType()});
+    $res = builder.CreateCall(fn, {$in});
+  }];
+}
+
+def LLVM_Log10Op : LLVM_Op<"intr.log10", [NoSideEffect]>,
+                   Arguments<(ins LLVM_Type:$in)>,
+                   Results<(outs LLVM_Type:$res)> {
+  let llvmBuilder = [{
+    llvm::Module *module = builder.GetInsertBlock()->getModule();
+    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
+        module, llvm::Intrinsic::log10, {$in->getType()});
+    $res = builder.CreateCall(fn, {$in});
+  }];
+}
+
+def LLVM_Log2Op : LLVM_Op<"intr.log2", [NoSideEffect]>,
+                   Arguments<(ins LLVM_Type:$in)>,
+                   Results<(outs LLVM_Type:$res)> {
+  let llvmBuilder = [{
+    llvm::Module *module = builder.GetInsertBlock()->getModule();
+    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
+        module, llvm::Intrinsic::log2, {$in->getType()});
+    $res = builder.CreateCall(fn, {$in});
+  }];
+}
+
 #endif // LLVMIR_OPS
index c67e345..8e21a8b 100644 (file)
@@ -837,6 +837,18 @@ def LoadOp : Std_Op<"load"> {
   let hasCanonicalizer = 1;
 }
 
+def LogOp : FloatUnaryOp<"log"> {
+  let summary = "base-e logarithm of the specified value";
+}
+
+def Log10Op : FloatUnaryOp<"log10"> {
+  let summary = "base-10 logarithm of the specified value";
+}
+
+def Log2Op : FloatUnaryOp<"log2"> {
+  let summary = "base-2 logarithm of the specified value";
+}
+
 def MemRefCastOp : CastOp<"memref_cast"> {
   let summary = "memref cast operation";
   let description = [{
index 794683e..933c0cf 100644 (file)
@@ -812,6 +812,15 @@ using BinaryOpLLVMOpLowering = NaryOpLLVMOpLowering<SourceOp, TargetOp, 2>;
 struct ExpOpLowering : public UnaryOpLLVMOpLowering<ExpOp, LLVM::ExpOp> {
   using Super::Super;
 };
+struct LogOpLowering : public UnaryOpLLVMOpLowering<LogOp, LLVM::LogOp> {
+  using Super::Super;
+};
+struct Log10OpLowering : public UnaryOpLLVMOpLowering<Log10Op, LLVM::Log10Op> {
+  using Super::Super;
+};
+struct Log2OpLowering : public UnaryOpLLVMOpLowering<Log2Op, LLVM::Log2Op> {
+  using Super::Super;
+};
 struct AddIOpLowering : public BinaryOpLLVMOpLowering<AddIOp, LLVM::AddOp> {
   using Super::Super;
 };
@@ -2004,6 +2013,9 @@ void mlir::populateStdToLLVMConversionPatterns(
       DivISOpLowering,
       DivIUOpLowering,
       ExpOpLowering,
+      LogOpLowering,
+      Log10OpLowering,
+      Log2OpLowering,
       FPExtLowering,
       FPTruncLowering,
       FuncOpConversion,
index bc08a04..2a85569 100644 (file)
@@ -18,8 +18,41 @@ llvm.func @exp_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) {
   llvm.return
 }
 
+// CHECK-LABEL: @log_test
+llvm.func @log_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) {
+  // CHECK: call float @llvm.log.f32
+  "llvm.intr.log"(%arg0) : (!llvm.float) -> !llvm.float
+  // CHECK: call <8 x float> @llvm.log.v8f32
+  "llvm.intr.log"(%arg1) : (!llvm<"<8 x float>">) -> !llvm<"<8 x float>">
+  llvm.return
+}
+
+// CHECK-LABEL: @log10_test
+llvm.func @log10_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) {
+  // CHECK: call float @llvm.log10.f32
+  "llvm.intr.log10"(%arg0) : (!llvm.float) -> !llvm.float
+  // CHECK: call <8 x float> @llvm.log10.v8f32
+  "llvm.intr.log10"(%arg1) : (!llvm<"<8 x float>">) -> !llvm<"<8 x float>">
+  llvm.return
+}
+
+// CHECK-LABEL: @log2_test
+llvm.func @log2_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) {
+  // CHECK: call float @llvm.log2.f32
+  "llvm.intr.log2"(%arg0) : (!llvm.float) -> !llvm.float
+  // CHECK: call <8 x float> @llvm.log2.v8f32
+  "llvm.intr.log2"(%arg1) : (!llvm<"<8 x float>">) -> !llvm<"<8 x float>">
+  llvm.return
+}
+
 // Check that intrinsics are declared with appropriate types.
 // CHECK: declare float @llvm.fmuladd.f32.f32.f32(float, float, float)
 // CHECK: declare <8 x float> @llvm.fmuladd.v8f32.v8f32.v8f32(<8 x float>, <8 x float>, <8 x float>) #0
 // CHECK: declare float @llvm.exp.f32(float)
 // CHECK: declare <8 x float> @llvm.exp.v8f32(<8 x float>) #0
+// CHECK: declare float @llvm.log.f32(float)
+// CHECK: declare <8 x float> @llvm.log.v8f32(<8 x float>) #0
+// CHECK: declare float @llvm.log10.f32(float)
+// CHECK: declare <8 x float> @llvm.log10.v8f32(<8 x float>) #0
+// CHECK: declare float @llvm.log2.f32(float)
+// CHECK: declare <8 x float> @llvm.log2.v8f32(<8 x float>) #0