diff --git a/mlir/include/mlir/Dialect/Math/IR/MathOps.td b/mlir/include/mlir/Dialect/Math/IR/MathOps.td --- a/mlir/include/mlir/Dialect/Math/IR/MathOps.td +++ b/mlir/include/mlir/Dialect/Math/IR/MathOps.td @@ -632,6 +632,26 @@ let hasFolder = 1; } +//===----------------------------------------------------------------------===// +// TanOp +//===----------------------------------------------------------------------===// + +def Math_TanOp : Math_FloatUnaryOp<"tan"> { + let summary = "tangent of the specified value"; + let description = [{ + The `tan` operation computes the tangent. It takes one operand + of floating point type (i.e., scalar, tensor or vector) and returns one + result of the same type. It has no standard attributes. + + Example: + + ```mlir + // Scalar tangent value. + %a = math.tan %b : f64 + ``` + }]; +} + //===----------------------------------------------------------------------===// // TanhOp //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp b/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp --- a/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp +++ b/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp @@ -143,13 +143,13 @@ patterns.add, VecOpToScalarOp, VecOpToScalarOp, VecOpToScalarOp, VecOpToScalarOp, VecOpToScalarOp, - VecOpToScalarOp, VecOpToScalarOp>( - patterns.getContext(), benefit); + VecOpToScalarOp, VecOpToScalarOp, + VecOpToScalarOp>(patterns.getContext(), benefit); patterns.add, PromoteOpToF32, PromoteOpToF32, PromoteOpToF32, PromoteOpToF32, PromoteOpToF32, - PromoteOpToF32, PromoteOpToF32>( - patterns.getContext(), benefit); + PromoteOpToF32, PromoteOpToF32, + PromoteOpToF32>(patterns.getContext(), benefit); patterns.add>(patterns.getContext(), "atanf", "atan", benefit); patterns.add>(patterns.getContext(), @@ -158,6 +158,8 @@ "erf", benefit); patterns.add>(patterns.getContext(), "expm1f", "expm1", benefit); + patterns.add>(patterns.getContext(), "tanf", + "tan", benefit); patterns.add>(patterns.getContext(), "tanhf", "tanh", benefit); patterns.add>(patterns.getContext(), diff --git a/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir b/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir --- a/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir +++ b/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir @@ -8,6 +8,8 @@ // CHECK-DAG: @expm1f(f32) -> f32 // CHECK-DAG: @atan2(f64, f64) -> f64 // CHECK-DAG: @atan2f(f32, f32) -> f32 +// CHECK-DAG: @tan(f64) -> f64 +// CHECK-DAG: @tanf(f32) -> f32 // CHECK-DAG: @tanh(f64) -> f64 // CHECK-DAG: @tanhf(f32) -> f32 // CHECK-DAG: @round(f64) -> f64 @@ -254,3 +256,50 @@ // CHECK: return %[[VAL_11]], %[[VAL_17]] : vector<2xf32>, vector<2xf64> return %float_result, %double_result : vector<2xf32>, vector<2xf64> } + +// CHECK-LABEL: func @tan_caller +// CHECK-SAME: %[[FLOAT:.*]]: f32 +// CHECK-SAME: %[[DOUBLE:.*]]: f64 +// CHECK-SAME: %[[HALF:.*]]: f16 +// CHECK-SAME: %[[BFLOAT:.*]]: bf16 +func.func @tan_caller(%float: f32, %double: f64, %half: f16, %bfloat: bf16) -> (f32, f64, f16, bf16) { + // CHECK: %[[FLOAT_RESULT:.*]] = call @tanf(%[[FLOAT]]) : (f32) -> f32 + %float_result = math.tan %float : f32 + // CHECK: %[[DOUBLE_RESULT:.*]] = call @tan(%[[DOUBLE]]) : (f64) -> f64 + %double_result = math.tan %double : f64 + // CHECK: %[[HALF_PROMOTED:.*]] = arith.extf %[[HALF]] : f16 to f32 + // CHECK: %[[HALF_CALL:.*]] = call @tanf(%[[HALF_PROMOTED]]) : (f32) -> f32 + // CHECK: %[[HALF_RESULT:.*]] = arith.truncf %[[HALF_CALL]] : f32 to f16 + %half_result = math.tan %half : f16 + // CHECK: %[[BFLOAT_PROMOTED:.*]] = arith.extf %[[BFLOAT]] : bf16 to f32 + // CHECK: %[[BFLOAT_CALL:.*]] = call @tanf(%[[BFLOAT_PROMOTED]]) : (f32) -> f32 + // CHECK: %[[BFLOAT_RESULT:.*]] = arith.truncf %[[BFLOAT_CALL]] : f32 to bf16 + %bfloat_result = math.tan %bfloat : bf16 + // CHECK: return %[[FLOAT_RESULT]], %[[DOUBLE_RESULT]], %[[HALF_RESULT]], %[[BFLOAT_RESULT]] + return %float_result, %double_result, %half_result, %bfloat_result : f32, f64, f16, bf16 +} + +// CHECK-LABEL: func @tan_vec_caller( +// CHECK-SAME: %[[VAL_0:.*]]: vector<2xf32>, +// CHECK-SAME: %[[VAL_1:.*]]: vector<2xf64>) -> (vector<2xf32>, vector<2xf64>) { +// CHECK-DAG: %[[CVF:.*]] = arith.constant dense<0.000000e+00> : vector<2xf32> +// CHECK-DAG: %[[CVD:.*]] = arith.constant dense<0.000000e+00> : vector<2xf64> +// CHECK: %[[IN0_F32:.*]] = vector.extract %[[VAL_0]][0] : vector<2xf32> +// CHECK: %[[OUT0_F32:.*]] = call @tanf(%[[IN0_F32]]) : (f32) -> f32 +// CHECK: %[[VAL_8:.*]] = vector.insert %[[OUT0_F32]], %[[CVF]] [0] : f32 into vector<2xf32> +// CHECK: %[[IN1_F32:.*]] = vector.extract %[[VAL_0]][1] : vector<2xf32> +// CHECK: %[[OUT1_F32:.*]] = call @tanf(%[[IN1_F32]]) : (f32) -> f32 +// CHECK: %[[VAL_11:.*]] = vector.insert %[[OUT1_F32]], %[[VAL_8]] [1] : f32 into vector<2xf32> +// CHECK: %[[IN0_F64:.*]] = vector.extract %[[VAL_1]][0] : vector<2xf64> +// CHECK: %[[OUT0_F64:.*]] = call @tan(%[[IN0_F64]]) : (f64) -> f64 +// CHECK: %[[VAL_14:.*]] = vector.insert %[[OUT0_F64]], %[[CVD]] [0] : f64 into vector<2xf64> +// CHECK: %[[IN1_F64:.*]] = vector.extract %[[VAL_1]][1] : vector<2xf64> +// CHECK: %[[OUT1_F64:.*]] = call @tan(%[[IN1_F64]]) : (f64) -> f64 +// CHECK: %[[VAL_17:.*]] = vector.insert %[[OUT1_F64]], %[[VAL_14]] [1] : f64 into vector<2xf64> +// CHECK: return %[[VAL_11]], %[[VAL_17]] : vector<2xf32>, vector<2xf64> +// CHECK: } +func.func @tan_vec_caller(%float: vector<2xf32>, %double: vector<2xf64>) -> (vector<2xf32>, vector<2xf64>) { + %float_result = math.tan %float : vector<2xf32> + %double_result = math.tan %double : vector<2xf64> + return %float_result, %double_result : vector<2xf32>, vector<2xf64> +} diff --git a/mlir/test/Dialect/Math/ops.mlir b/mlir/test/Dialect/Math/ops.mlir --- a/mlir/test/Dialect/Math/ops.mlir +++ b/mlir/test/Dialect/Math/ops.mlir @@ -183,6 +183,18 @@ return } +// CHECK-LABEL: func @tan( +// CHECK-SAME: %[[F:.*]]: f32, %[[V:.*]]: vector<4xf32>, %[[T:.*]]: tensor<4x4x?xf32>) +func.func @tan(%f: f32, %v: vector<4xf32>, %t: tensor<4x4x?xf32>) { + // CHECK: %{{.*}} = math.tan %[[F]] : f32 + %0 = math.tan %f : f32 + // CHECK: %{{.*}} = math.tan %[[V]] : vector<4xf32> + %1 = math.tan %v : vector<4xf32> + // CHECK: %{{.*}} = math.tan %[[T]] : tensor<4x4x?xf32> + %2 = math.tan %t : tensor<4x4x?xf32> + return +} + // CHECK-LABEL: func @tanh( // CHECK-SAME: %[[F:.*]]: f32, %[[V:.*]]: vector<4xf32>, %[[T:.*]]: tensor<4x4x?xf32>) func.func @tanh(%f: f32, %v: vector<4xf32>, %t: tensor<4x4x?xf32>) {