From da6168bbc1a369ae2e99ad3881fdddd82f075dd4 Mon Sep 17 00:00:00 2001 From: Marcel Koester Date: Wed, 20 Nov 2019 13:53:06 +0100 Subject: [PATCH] Added LLVM ops and lowering phases from standard dialect for FAbs, FCeil, Cos, FNeg, CopySign and Tanh. Added test cases for the newly added LLVM operations and lowering features. --- include/mlir/Dialect/LLVMIR/LLVMOps.td | 49 ++++++++++++------- .../StandardToLLVM/ConvertStandardToLLVM.cpp | 20 ++++++++ test/Target/llvmir-intrinsics.mlir | 42 ++++++++++++++++ 3 files changed, 92 insertions(+), 19 deletions(-) diff --git a/include/mlir/Dialect/LLVMIR/LLVMOps.td b/include/mlir/Dialect/LLVMIR/LLVMOps.td index a7119147fc57..172290f25506 100644 --- a/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -662,29 +662,40 @@ def LLVM_ConstantOp // operations and intrinsics. However, we systematically prefix them with // "intr." to avoid potential name clashes. -def LLVM_FMulAddOp : LLVM_Op<"intr.fmuladd", [NoSideEffect]>, - Arguments<(ins LLVM_Type:$a, LLVM_Type:$b, LLVM_Type:$c)>, - Results<(outs LLVM_Type:$res)> { - let llvmBuilder = [{ - llvm::Module *module = builder.GetInsertBlock()->getModule(); - llvm::Function *fn = llvm::Intrinsic::getDeclaration( - module, llvm::Intrinsic::fmuladd, - {$a->getType(), $b->getType(), $c->getType()}); - $res = builder.CreateCall(fn, {$a, $b, $c}); - }]; +class LLVM_UnaryIntrinsicOp traits = []> : + LLVM_OneResultOp<"intr." # func, + !listconcat([NoSideEffect, SameOperandsAndResultType], traits)>, + Arguments<(ins LLVM_Type:$in)>, + LLVM_Builder<"$res = builder.CreateCall(llvm::Intrinsic::getDeclaration(" + "builder.GetInsertBlock()->getModule(), llvm::Intrinsic::" # func # "," + "{$in->getType()}), {$in});"> { } -def LLVM_ExpOp : LLVM_Op<"intr.exp", [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::exp, {$in->getType()}); - $res = builder.CreateCall(fn, {$in}); - }]; +class LLVM_BinaryIntrinsicOp traits = []> : + LLVM_OneResultOp<"intr." # func, + !listconcat([NoSideEffect, SameOperandsAndResultType], traits)>, + Arguments<(ins LLVM_Type:$a, LLVM_Type:$b)>, + LLVM_Builder<"$res = builder.CreateCall(llvm::Intrinsic::getDeclaration(" + "builder.GetInsertBlock()->getModule(), llvm::Intrinsic::" # func # "," + "{$a->getType(), $b->getType()}), {$a, $b});"> { } +class LLVM_TernaryIntrinsicOp traits = []> : + LLVM_OneResultOp<"intr." # func, + !listconcat([NoSideEffect, SameOperandsAndResultType], traits)>, + Arguments<(ins LLVM_Type:$a, LLVM_Type:$b, LLVM_Type:$c)>, + LLVM_Builder<"$res = builder.CreateCall(llvm::Intrinsic::getDeclaration(" + "builder.GetInsertBlock()->getModule(), llvm::Intrinsic::" # func # "," + "{$a->getType(), $b->getType(), $c->getType()}), {$a, $b, $c});"> { +} + +def LLVM_ExpOp : LLVM_UnaryIntrinsicOp<"exp">; +def LLVM_FAbsOp : LLVM_UnaryIntrinsicOp<"fabs">; +def LLVM_FCeilOp : LLVM_UnaryIntrinsicOp<"ceil">; +def LLVM_CosOp : LLVM_UnaryIntrinsicOp<"cos">; +def LLVM_CopySignOp : LLVM_BinaryIntrinsicOp<"copysign">; +def LLVM_FMulAddOp : LLVM_TernaryIntrinsicOp<"fmuladd">; + def LLVM_LogOp : LLVM_Op<"intr.log", [NoSideEffect]>, Arguments<(ins LLVM_Type:$in)>, Results<(outs LLVM_Type:$res)> { diff --git a/lib/Conversion/StandardToLLVM/ConvertStandardToLLVM.cpp b/lib/Conversion/StandardToLLVM/ConvertStandardToLLVM.cpp index 508868de54df..0fb75ace9066 100644 --- a/lib/Conversion/StandardToLLVM/ConvertStandardToLLVM.cpp +++ b/lib/Conversion/StandardToLLVM/ConvertStandardToLLVM.cpp @@ -809,6 +809,15 @@ using BinaryOpLLVMOpLowering = NaryOpLLVMOpLowering; // Specific lowerings. // FIXME: this should be tablegen'ed. +struct AbsFOpLowering : public UnaryOpLLVMOpLowering { + using Super::Super; +}; +struct CeilFOpLowering : public UnaryOpLLVMOpLowering { + using Super::Super; +}; +struct CosOpLowering : public UnaryOpLLVMOpLowering { + using Super::Super; +}; struct ExpOpLowering : public UnaryOpLLVMOpLowering { using Super::Super; }; @@ -821,6 +830,9 @@ struct Log10OpLowering : public UnaryOpLLVMOpLowering { struct Log2OpLowering : public UnaryOpLLVMOpLowering { using Super::Super; }; +struct NegFOpLowering : public UnaryOpLLVMOpLowering { + using Super::Super; +}; struct AddIOpLowering : public BinaryOpLLVMOpLowering { using Super::Super; }; @@ -866,6 +878,9 @@ struct DivFOpLowering : public BinaryOpLLVMOpLowering { struct RemFOpLowering : public BinaryOpLLVMOpLowering { using Super::Super; }; +struct CopySignOpLowering : public BinaryOpLLVMOpLowering { + using Super::Super; +}; struct SelectOpLowering : public OneToOneLLVMOpLowering { using Super::Super; @@ -2048,15 +2063,19 @@ void mlir::populateStdToLLVMConversionPatterns( // FIXME: this should be tablegen'ed // clang-format off patterns.insert< + AbsFOpLowering, AddFOpLowering, AddIOpLowering, AndOpLowering, BranchOpLowering, CallIndirectOpLowering, CallOpLowering, + CeilFOpLowering, CmpFOpLowering, CmpIOpLowering, CondBranchOpLowering, + CopySignOpLowering, + CosOpLowering, ConstLLVMOpLowering, DimOpLowering, DivFOpLowering, @@ -2074,6 +2093,7 @@ void mlir::populateStdToLLVMConversionPatterns( MemRefCastOpLowering, MulFOpLowering, MulIOpLowering, + NegFOpLowering, OrOpLowering, RemFOpLowering, RemISOpLowering, diff --git a/test/Target/llvmir-intrinsics.mlir b/test/Target/llvmir-intrinsics.mlir index 2a85569546fd..79709f6d4f23 100644 --- a/test/Target/llvmir-intrinsics.mlir +++ b/test/Target/llvmir-intrinsics.mlir @@ -45,6 +45,42 @@ llvm.func @log2_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) { llvm.return } +// CHECK-LABEL: @fabs_test +llvm.func @fabs_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) { + // CHECK: call float @llvm.fabs.f32 + "llvm.intr.fabs"(%arg0) : (!llvm.float) -> !llvm.float + // CHECK: call <8 x float> @llvm.fabs.v8f32 + "llvm.intr.fabs"(%arg1) : (!llvm<"<8 x float>">) -> !llvm<"<8 x float>"> + llvm.return +} + +// CHECK-LABEL: @ceil_test +llvm.func @ceil_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) { + // CHECK: call float @llvm.ceil.f32 + "llvm.intr.ceil"(%arg0) : (!llvm.float) -> !llvm.float + // CHECK: call <8 x float> @llvm.ceil.v8f32 + "llvm.intr.ceil"(%arg1) : (!llvm<"<8 x float>">) -> !llvm<"<8 x float>"> + llvm.return +} + +// CHECK-LABEL: @cos_test +llvm.func @cos_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x float>">) { + // CHECK: call float @llvm.cos.f32 + "llvm.intr.cos"(%arg0) : (!llvm.float) -> !llvm.float + // CHECK: call <8 x float> @llvm.cos.v8f32 + "llvm.intr.cos"(%arg1) : (!llvm<"<8 x float>">) -> !llvm<"<8 x float>"> + llvm.return +} + +// CHECK-LABEL: @copysign_test +llvm.func @copysign_test(%arg0: !llvm.float, %arg1: !llvm.float, %arg2: !llvm<"<8 x float>">, %arg3: !llvm<"<8 x float>">) { + // CHECK: call float @llvm.copysign.f32 + "llvm.intr.copysign"(%arg0, %arg1) : (!llvm.float, !llvm.float) -> !llvm.float + // CHECK: call <8 x float> @llvm.copysign.v8f32 + "llvm.intr.copysign"(%arg2, %arg3) : (!llvm<"<8 x float>">, !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 @@ -56,3 +92,9 @@ llvm.func @log2_test(%arg0: !llvm.float, %arg1: !llvm<"<8 x 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 +// CHECK: declare float @llvm.fabs.f32(float) +// CHECK: declare <8 x float> @llvm.fabs.v8f32(<8 x float>) #0 +// CHECK: declare float @llvm.ceil.f32(float) +// CHECK: declare <8 x float> @llvm.ceil.v8f32(<8 x float>) #0 +// CHECK: declare float @llvm.cos.f32(float) +// CHECK: declare <8 x float> @llvm.cos.v8f32(<8 x float>) #0