[llvm] [DirectX] Add trig intrinsics and link them with DXIL backend (PR #95968)

Farzon Lotfi via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 18 11:27:55 PDT 2024


https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/95968

>From 0d08c6446bd1793a7a0ac789548f656ab0ffec3e Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 18 Jun 2024 14:07:23 -0400
Subject: [PATCH] [DirectX] Add trig intrinsics and link them with DXIL backend
 This change is part of this proposal:
 https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294

This is part 1 of 4 PRs. It sets the ground work for adding the
intrinsics.

Add DXIL Lower for acos, asin, atan, cosh, sinh, and tanh
https://github.com/llvm/llvm-project/issues/70079
https://github.com/llvm/llvm-project/issues/70080
https://github.com/llvm/llvm-project/issues/70081
https://github.com/llvm/llvm-project/issues/70083
https://github.com/llvm/llvm-project/issues/70084
https://github.com/llvm/llvm-project/issues/95966
---
 llvm/docs/LangRef.rst                   | 222 ++++++++++++++++++++++++
 llvm/include/llvm/IR/Intrinsics.td      |   6 +
 llvm/lib/Target/DirectX/DXIL.td         |  19 ++
 llvm/test/CodeGen/DirectX/acos.ll       |  20 +++
 llvm/test/CodeGen/DirectX/acos_error.ll |  10 ++
 llvm/test/CodeGen/DirectX/asin.ll       |  20 +++
 llvm/test/CodeGen/DirectX/asin_error.ll |  10 ++
 llvm/test/CodeGen/DirectX/atan.ll       |  20 +++
 llvm/test/CodeGen/DirectX/atan_error.ll |  10 ++
 llvm/test/CodeGen/DirectX/cosh.ll       |  20 +++
 llvm/test/CodeGen/DirectX/cosh_error.ll |  10 ++
 llvm/test/CodeGen/DirectX/sinh.ll       |  20 +++
 llvm/test/CodeGen/DirectX/sinh_error.ll |  10 ++
 llvm/test/CodeGen/DirectX/tanh.ll       |  20 +++
 llvm/test/CodeGen/DirectX/tanh_error.ll |  10 ++
 15 files changed, 427 insertions(+)
 create mode 100644 llvm/test/CodeGen/DirectX/acos.ll
 create mode 100644 llvm/test/CodeGen/DirectX/acos_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/asin.ll
 create mode 100644 llvm/test/CodeGen/DirectX/asin_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/atan.ll
 create mode 100644 llvm/test/CodeGen/DirectX/atan_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/cosh.ll
 create mode 100644 llvm/test/CodeGen/DirectX/cosh_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/sinh.ll
 create mode 100644 llvm/test/CodeGen/DirectX/sinh_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/tanh.ll
 create mode 100644 llvm/test/CodeGen/DirectX/tanh_error.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 5a1535cb782fb..ed2de254e7fb5 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -15384,6 +15384,228 @@ trapping or setting ``errno``.
 When specified with the fast-math-flag 'afn', the result may be approximated
 using a less accurate calculation.
 
+'``llvm.asin.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.asin`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.asin.f32(float  %Val)
+      declare double    @llvm.asin.f64(double %Val)
+      declare x86_fp80  @llvm.asin.f80(x86_fp80  %Val)
+      declare fp128     @llvm.asin.f128(fp128 %Val)
+      declare ppc_fp128 @llvm.asin.ppcf128(ppc_fp128  %Val)
+
+Overview:
+"""""""""
+
+The '``llvm.asin.*``' intrinsics return the arcsine of the operand.
+
+Arguments:
+""""""""""
+
+The argument and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Return the same value as a corresponding libm '``asin``' function but without
+trapping or setting ``errno``.
+
+When specified with the fast-math-flag 'afn', the result may be approximated
+using a less accurate calculation.
+
+'``llvm.acos.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.acos`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.acos.f32(float  %Val)
+      declare double    @llvm.acos.f64(double %Val)
+      declare x86_fp80  @llvm.acos.f80(x86_fp80  %Val)
+      declare fp128     @llvm.acos.f128(fp128 %Val)
+      declare ppc_fp128 @llvm.acos.ppcf128(ppc_fp128  %Val)
+
+Overview:
+"""""""""
+
+The '``llvm.acos.*``' intrinsics return the arccosine of the operand.
+
+Arguments:
+""""""""""
+
+The argument and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Return the same value as a corresponding libm '``acos``' function but without
+trapping or setting ``errno``.
+
+When specified with the fast-math-flag 'afn', the result may be approximated
+using a less accurate calculation.
+
+'``llvm.atan.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.atan`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.atan.f32(float  %Val)
+      declare double    @llvm.atan.f64(double %Val)
+      declare x86_fp80  @llvm.atan.f80(x86_fp80  %Val)
+      declare fp128     @llvm.atan.f128(fp128 %Val)
+      declare ppc_fp128 @llvm.atan.ppcf128(ppc_fp128  %Val)
+
+Overview:
+"""""""""
+
+The '``llvm.atan.*``' intrinsics return the arctangent of the operand.
+
+Arguments:
+""""""""""
+
+The argument and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Return the same value as a corresponding libm '``atan``' function but without
+trapping or setting ``errno``.
+
+When specified with the fast-math-flag 'afn', the result may be approximated
+using a less accurate calculation.
+
+'``llvm.sinh.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.sinh`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.sinh.f32(float  %Val)
+      declare double    @llvm.sinh.f64(double %Val)
+      declare x86_fp80  @llvm.sinh.f80(x86_fp80  %Val)
+      declare fp128     @llvm.sinh.f128(fp128 %Val)
+      declare ppc_fp128 @llvm.sinh.ppcf128(ppc_fp128  %Val)
+
+Overview:
+"""""""""
+
+The '``llvm.sinh.*``' intrinsics return the hyperbolic sine of the operand.
+
+Arguments:
+""""""""""
+
+The argument and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Return the same value as a corresponding libm '``sinh``' function but without
+trapping or setting ``errno``.
+
+When specified with the fast-math-flag 'afn', the result may be approximated
+using a less accurate calculation.
+
+'``llvm.cosh.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.cosh`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.cosh.f32(float  %Val)
+      declare double    @llvm.cosh.f64(double %Val)
+      declare x86_fp80  @llvm.cosh.f80(x86_fp80  %Val)
+      declare fp128     @llvm.cosh.f128(fp128 %Val)
+      declare ppc_fp128 @llvm.cosh.ppcf128(ppc_fp128  %Val)
+
+Overview:
+"""""""""
+
+The '``llvm.cosh.*``' intrinsics return the hyperbolic cosine of the operand.
+
+Arguments:
+""""""""""
+
+The argument and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Return the same value as a corresponding libm '``cosh``' function but without
+trapping or setting ``errno``.
+
+When specified with the fast-math-flag 'afn', the result may be approximated
+using a less accurate calculation.
+
+'``llvm.tanh.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.tanh`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.tanh.f32(float  %Val)
+      declare double    @llvm.tanh.f64(double %Val)
+      declare x86_fp80  @llvm.tanh.f80(x86_fp80  %Val)
+      declare fp128     @llvm.tanh.f128(fp128 %Val)
+      declare ppc_fp128 @llvm.tanh.ppcf128(ppc_fp128  %Val)
+
+Overview:
+"""""""""
+
+The '``llvm.tanh.*``' intrinsics return the hyperbolic tangent of the operand.
+
+Arguments:
+""""""""""
+
+The argument and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Return the same value as a corresponding libm '``tanh``' function but without
+trapping or setting ``errno``.
+
+When specified with the fast-math-flag 'afn', the result may be approximated
+using a less accurate calculation.
+
 '``llvm.pow.*``' Intrinsic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index ef500329d1fb9..c7d383a5d0c0c 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -1019,9 +1019,15 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
   // environment so they can be treated as readnone.
   def int_sqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_powi : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>;
+  def int_asin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
+  def int_acos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
+  def int_atan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_sin  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_cos  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_tan  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
+  def int_sinh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
+  def int_cosh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
+  def int_tanh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
   def int_pow  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
                            [LLVMMatchType<0>, LLVMMatchType<0>]>;
   def int_log  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 24a0c8524230c..adaaa2a6e0d4e 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -269,6 +269,25 @@ def Sin  : DXILOpMapping<13, unary, int_sin,
 def Tan  : DXILOpMapping<14, unary, int_tan,
                          "Returns tangent(theta) for theta in radians.",
                          [llvm_halforfloat_ty, LLVMMatchType<0>]>;
+def ACos  : DXILOpMapping<15, unary, int_acos,
+                         "Returns the arccosine of each component of input.",
+                         [llvm_halforfloat_ty, LLVMMatchType<0>]>;
+def ASin  : DXILOpMapping<16, unary, int_asin,
+                         "Returns the arcsine of each component of input.",
+                         [llvm_halforfloat_ty, LLVMMatchType<0>]>;
+def ATan  : DXILOpMapping<17, unary, int_atan,
+                         "Returns the arctangent of each component of input.",
+                         [llvm_halforfloat_ty, LLVMMatchType<0>]>;
+def HCos  : DXILOpMapping<18, unary, int_cosh,
+                         "Returns the hyperbolic cosine of the specified value.",
+                         [llvm_halforfloat_ty, LLVMMatchType<0>]>;
+def HSin  : DXILOpMapping<19, unary, int_sinh,
+                         "Returns the hyperbolic sine of the specified value.",
+                         [llvm_halforfloat_ty, LLVMMatchType<0>]>;
+def HTan  : DXILOpMapping<20, unary, int_tanh,
+                         "Returns the hyperbolic tan of the specified value.",
+                         [llvm_halforfloat_ty, LLVMMatchType<0>]>;
+
 def Exp2 : DXILOpMapping<21, unary, int_exp2,
                          "Returns the base 2 exponential, or 2**x, of the specified value."
                          "exp2(x) = 2**x.",
diff --git a/llvm/test/CodeGen/DirectX/acos.ll b/llvm/test/CodeGen/DirectX/acos.ll
new file mode 100644
index 0000000000000..31b08833f45a1
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/acos.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+
+; Make sure dxil operation function calls for acos are generated for float and half.
+
+define noundef float @tan_float(float noundef %a) {
+entry:
+; CHECK:call float @dx.op.unary.f32(i32 15, float %{{.*}})
+  %elt.acos = call float @llvm.acos.f32(float %a)
+  ret float %elt.acos
+}
+
+define noundef half @tan_half(half noundef %a) {
+entry:
+; CHECK:call half @dx.op.unary.f16(i32 15, half %{{.*}})
+  %elt.acos = call half @llvm.acos.f16(half %a)
+  ret half %elt.acos
+}
+
+declare half @llvm.acos.f16(half)
+declare float @llvm.acos.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/acos_error.ll b/llvm/test/CodeGen/DirectX/acos_error.ll
new file mode 100644
index 0000000000000..e0474e9b758e7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/acos_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+
+; DXIL operation acos does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload
+
+define noundef double @acos_double(double noundef %a) {
+entry:
+  %1 = call double @llvm.acos.f64(double %a)
+  ret double %1
+}
diff --git a/llvm/test/CodeGen/DirectX/asin.ll b/llvm/test/CodeGen/DirectX/asin.ll
new file mode 100644
index 0000000000000..56c2d86be3547
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/asin.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+
+; Make sure dxil operation function calls for asin are generated for float and half.
+
+define noundef float @tan_float(float noundef %a) {
+entry:
+; CHECK:call float @dx.op.unary.f32(i32 16, float %{{.*}})
+  %elt.asin = call float @llvm.asin.f32(float %a)
+  ret float %elt.asin
+}
+
+define noundef half @tan_half(half noundef %a) {
+entry:
+; CHECK:call half @dx.op.unary.f16(i32 16, half %{{.*}})
+  %elt.asin = call half @llvm.asin.f16(half %a)
+  ret half %elt.asin
+}
+
+declare half @llvm.asin.f16(half)
+declare float @llvm.asin.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/asin_error.ll b/llvm/test/CodeGen/DirectX/asin_error.ll
new file mode 100644
index 0000000000000..ddd4b2e424f62
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/asin_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+
+; DXIL operation asin does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload
+
+define noundef double @asin_double(double noundef %a) {
+entry:
+  %1 = call double @llvm.asin.f64(double %a)
+  ret double %1
+}
diff --git a/llvm/test/CodeGen/DirectX/atan.ll b/llvm/test/CodeGen/DirectX/atan.ll
new file mode 100644
index 0000000000000..7aa4418a59813
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/atan.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+
+; Make sure dxil operation function calls for atan are generated for float and half.
+
+define noundef float @tan_float(float noundef %a) {
+entry:
+; CHECK:call float @dx.op.unary.f32(i32 17, float %{{.*}})
+  %elt.atan = call float @llvm.atan.f32(float %a)
+  ret float %elt.atan
+}
+
+define noundef half @tan_half(half noundef %a) {
+entry:
+; CHECK:call half @dx.op.unary.f16(i32 17, half %{{.*}})
+  %elt.atan = call half @llvm.atan.f16(half %a)
+  ret half %elt.atan
+}
+
+declare half @llvm.atan.f16(half)
+declare float @llvm.atan.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/atan_error.ll b/llvm/test/CodeGen/DirectX/atan_error.ll
new file mode 100644
index 0000000000000..1880b1d38ba3c
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/atan_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+
+; DXIL operation atan does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload
+
+define noundef double @atan_double(double noundef %a) {
+entry:
+  %1 = call double @llvm.atan.f64(double %a)
+  ret double %1
+}
diff --git a/llvm/test/CodeGen/DirectX/cosh.ll b/llvm/test/CodeGen/DirectX/cosh.ll
new file mode 100644
index 0000000000000..4fe22f0a38ce1
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/cosh.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+
+; Make sure dxil operation function calls for cosh are generated for float and half.
+
+define noundef float @tan_float(float noundef %a) {
+entry:
+; CHECK:call float @dx.op.unary.f32(i32 18, float %{{.*}})
+  %elt.cosh = call float @llvm.cosh.f32(float %a)
+  ret float %elt.cosh
+}
+
+define noundef half @tan_half(half noundef %a) {
+entry:
+; CHECK:call half @dx.op.unary.f16(i32 18, half %{{.*}})
+  %elt.cosh = call half @llvm.cosh.f16(half %a)
+  ret half %elt.cosh
+}
+
+declare half @llvm.cosh.f16(half)
+declare float @llvm.cosh.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/cosh_error.ll b/llvm/test/CodeGen/DirectX/cosh_error.ll
new file mode 100644
index 0000000000000..cf66c54db1a08
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/cosh_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+
+; DXIL operation cosh does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload
+
+define noundef double @cosh_double(double noundef %a) {
+entry:
+  %1 = call double @llvm.cosh.f64(double %a)
+  ret double %1
+}
diff --git a/llvm/test/CodeGen/DirectX/sinh.ll b/llvm/test/CodeGen/DirectX/sinh.ll
new file mode 100644
index 0000000000000..76d189836f393
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/sinh.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+
+; Make sure dxil operation function calls for sinh are generated for float and half.
+
+define noundef float @tan_float(float noundef %a) {
+entry:
+; CHECK:call float @dx.op.unary.f32(i32 19, float %{{.*}})
+  %elt.sinh = call float @llvm.sinh.f32(float %a)
+  ret float %elt.sinh
+}
+
+define noundef half @tan_half(half noundef %a) {
+entry:
+; CHECK:call half @dx.op.unary.f16(i32 19, half %{{.*}})
+  %elt.sinh = call half @llvm.sinh.f16(half %a)
+  ret half %elt.sinh
+}
+
+declare half @llvm.sinh.f16(half)
+declare float @llvm.sinh.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/sinh_error.ll b/llvm/test/CodeGen/DirectX/sinh_error.ll
new file mode 100644
index 0000000000000..6a021ce88eb3b
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/sinh_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+
+; DXIL operation sinh does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload
+
+define noundef double @sinh_double(double noundef %a) {
+entry:
+  %1 = call double @llvm.sinh.f64(double %a)
+  ret double %1
+}
diff --git a/llvm/test/CodeGen/DirectX/tanh.ll b/llvm/test/CodeGen/DirectX/tanh.ll
new file mode 100644
index 0000000000000..d0313178c7ac3
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/tanh.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+
+; Make sure dxil operation function calls for tanh are generated for float and half.
+
+define noundef float @tan_float(float noundef %a) {
+entry:
+; CHECK:call float @dx.op.unary.f32(i32 20, float %{{.*}})
+  %elt.tanh = call float @llvm.tanh.f32(float %a)
+  ret float %elt.tanh
+}
+
+define noundef half @tan_half(half noundef %a) {
+entry:
+; CHECK:call half @dx.op.unary.f16(i32 20, half %{{.*}})
+  %elt.tanh = call half @llvm.tanh.f16(half %a)
+  ret half %elt.tanh
+}
+
+declare half @llvm.tanh.f16(half)
+declare float @llvm.tanh.f32(float)
diff --git a/llvm/test/CodeGen/DirectX/tanh_error.ll b/llvm/test/CodeGen/DirectX/tanh_error.ll
new file mode 100644
index 0000000000000..a1b8cbf0e13bc
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/tanh_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+
+; DXIL operation tanh does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload
+
+define noundef double @tanh_double(double noundef %a) {
+entry:
+  %1 = call double @llvm.tanh.f64(double %a)
+  ret double %1
+}



More information about the llvm-commits mailing list