Skip to content

Commit 936bc9b

Browse files
authored
[DirectX] Add trig intrinsics and link them with DXIL backend (#95968)
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` #70079 #70080 #70081 #70083 #70084 #95966
1 parent c6ed828 commit 936bc9b

File tree

15 files changed

+427
-0
lines changed

15 files changed

+427
-0
lines changed

llvm/docs/LangRef.rst

+222
Original file line numberDiff line numberDiff line change
@@ -15401,6 +15401,228 @@ trapping or setting ``errno``.
1540115401
When specified with the fast-math-flag 'afn', the result may be approximated
1540215402
using a less accurate calculation.
1540315403

15404+
'``llvm.asin.*``' Intrinsic
15405+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
15406+
15407+
Syntax:
15408+
"""""""
15409+
15410+
This is an overloaded intrinsic. You can use ``llvm.asin`` on any
15411+
floating-point or vector of floating-point type. Not all targets support
15412+
all types however.
15413+
15414+
::
15415+
15416+
declare float @llvm.asin.f32(float %Val)
15417+
declare double @llvm.asin.f64(double %Val)
15418+
declare x86_fp80 @llvm.asin.f80(x86_fp80 %Val)
15419+
declare fp128 @llvm.asin.f128(fp128 %Val)
15420+
declare ppc_fp128 @llvm.asin.ppcf128(ppc_fp128 %Val)
15421+
15422+
Overview:
15423+
"""""""""
15424+
15425+
The '``llvm.asin.*``' intrinsics return the arcsine of the operand.
15426+
15427+
Arguments:
15428+
""""""""""
15429+
15430+
The argument and return value are floating-point numbers of the same type.
15431+
15432+
Semantics:
15433+
""""""""""
15434+
15435+
Return the same value as a corresponding libm '``asin``' function but without
15436+
trapping or setting ``errno``.
15437+
15438+
When specified with the fast-math-flag 'afn', the result may be approximated
15439+
using a less accurate calculation.
15440+
15441+
'``llvm.acos.*``' Intrinsic
15442+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
15443+
15444+
Syntax:
15445+
"""""""
15446+
15447+
This is an overloaded intrinsic. You can use ``llvm.acos`` on any
15448+
floating-point or vector of floating-point type. Not all targets support
15449+
all types however.
15450+
15451+
::
15452+
15453+
declare float @llvm.acos.f32(float %Val)
15454+
declare double @llvm.acos.f64(double %Val)
15455+
declare x86_fp80 @llvm.acos.f80(x86_fp80 %Val)
15456+
declare fp128 @llvm.acos.f128(fp128 %Val)
15457+
declare ppc_fp128 @llvm.acos.ppcf128(ppc_fp128 %Val)
15458+
15459+
Overview:
15460+
"""""""""
15461+
15462+
The '``llvm.acos.*``' intrinsics return the arccosine of the operand.
15463+
15464+
Arguments:
15465+
""""""""""
15466+
15467+
The argument and return value are floating-point numbers of the same type.
15468+
15469+
Semantics:
15470+
""""""""""
15471+
15472+
Return the same value as a corresponding libm '``acos``' function but without
15473+
trapping or setting ``errno``.
15474+
15475+
When specified with the fast-math-flag 'afn', the result may be approximated
15476+
using a less accurate calculation.
15477+
15478+
'``llvm.atan.*``' Intrinsic
15479+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
15480+
15481+
Syntax:
15482+
"""""""
15483+
15484+
This is an overloaded intrinsic. You can use ``llvm.atan`` on any
15485+
floating-point or vector of floating-point type. Not all targets support
15486+
all types however.
15487+
15488+
::
15489+
15490+
declare float @llvm.atan.f32(float %Val)
15491+
declare double @llvm.atan.f64(double %Val)
15492+
declare x86_fp80 @llvm.atan.f80(x86_fp80 %Val)
15493+
declare fp128 @llvm.atan.f128(fp128 %Val)
15494+
declare ppc_fp128 @llvm.atan.ppcf128(ppc_fp128 %Val)
15495+
15496+
Overview:
15497+
"""""""""
15498+
15499+
The '``llvm.atan.*``' intrinsics return the arctangent of the operand.
15500+
15501+
Arguments:
15502+
""""""""""
15503+
15504+
The argument and return value are floating-point numbers of the same type.
15505+
15506+
Semantics:
15507+
""""""""""
15508+
15509+
Return the same value as a corresponding libm '``atan``' function but without
15510+
trapping or setting ``errno``.
15511+
15512+
When specified with the fast-math-flag 'afn', the result may be approximated
15513+
using a less accurate calculation.
15514+
15515+
'``llvm.sinh.*``' Intrinsic
15516+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
15517+
15518+
Syntax:
15519+
"""""""
15520+
15521+
This is an overloaded intrinsic. You can use ``llvm.sinh`` on any
15522+
floating-point or vector of floating-point type. Not all targets support
15523+
all types however.
15524+
15525+
::
15526+
15527+
declare float @llvm.sinh.f32(float %Val)
15528+
declare double @llvm.sinh.f64(double %Val)
15529+
declare x86_fp80 @llvm.sinh.f80(x86_fp80 %Val)
15530+
declare fp128 @llvm.sinh.f128(fp128 %Val)
15531+
declare ppc_fp128 @llvm.sinh.ppcf128(ppc_fp128 %Val)
15532+
15533+
Overview:
15534+
"""""""""
15535+
15536+
The '``llvm.sinh.*``' intrinsics return the hyperbolic sine of the operand.
15537+
15538+
Arguments:
15539+
""""""""""
15540+
15541+
The argument and return value are floating-point numbers of the same type.
15542+
15543+
Semantics:
15544+
""""""""""
15545+
15546+
Return the same value as a corresponding libm '``sinh``' function but without
15547+
trapping or setting ``errno``.
15548+
15549+
When specified with the fast-math-flag 'afn', the result may be approximated
15550+
using a less accurate calculation.
15551+
15552+
'``llvm.cosh.*``' Intrinsic
15553+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
15554+
15555+
Syntax:
15556+
"""""""
15557+
15558+
This is an overloaded intrinsic. You can use ``llvm.cosh`` on any
15559+
floating-point or vector of floating-point type. Not all targets support
15560+
all types however.
15561+
15562+
::
15563+
15564+
declare float @llvm.cosh.f32(float %Val)
15565+
declare double @llvm.cosh.f64(double %Val)
15566+
declare x86_fp80 @llvm.cosh.f80(x86_fp80 %Val)
15567+
declare fp128 @llvm.cosh.f128(fp128 %Val)
15568+
declare ppc_fp128 @llvm.cosh.ppcf128(ppc_fp128 %Val)
15569+
15570+
Overview:
15571+
"""""""""
15572+
15573+
The '``llvm.cosh.*``' intrinsics return the hyperbolic cosine of the operand.
15574+
15575+
Arguments:
15576+
""""""""""
15577+
15578+
The argument and return value are floating-point numbers of the same type.
15579+
15580+
Semantics:
15581+
""""""""""
15582+
15583+
Return the same value as a corresponding libm '``cosh``' function but without
15584+
trapping or setting ``errno``.
15585+
15586+
When specified with the fast-math-flag 'afn', the result may be approximated
15587+
using a less accurate calculation.
15588+
15589+
'``llvm.tanh.*``' Intrinsic
15590+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
15591+
15592+
Syntax:
15593+
"""""""
15594+
15595+
This is an overloaded intrinsic. You can use ``llvm.tanh`` on any
15596+
floating-point or vector of floating-point type. Not all targets support
15597+
all types however.
15598+
15599+
::
15600+
15601+
declare float @llvm.tanh.f32(float %Val)
15602+
declare double @llvm.tanh.f64(double %Val)
15603+
declare x86_fp80 @llvm.tanh.f80(x86_fp80 %Val)
15604+
declare fp128 @llvm.tanh.f128(fp128 %Val)
15605+
declare ppc_fp128 @llvm.tanh.ppcf128(ppc_fp128 %Val)
15606+
15607+
Overview:
15608+
"""""""""
15609+
15610+
The '``llvm.tanh.*``' intrinsics return the hyperbolic tangent of the operand.
15611+
15612+
Arguments:
15613+
""""""""""
15614+
15615+
The argument and return value are floating-point numbers of the same type.
15616+
15617+
Semantics:
15618+
""""""""""
15619+
15620+
Return the same value as a corresponding libm '``tanh``' function but without
15621+
trapping or setting ``errno``.
15622+
15623+
When specified with the fast-math-flag 'afn', the result may be approximated
15624+
using a less accurate calculation.
15625+
1540415626
'``llvm.pow.*``' Intrinsic
1540515627
^^^^^^^^^^^^^^^^^^^^^^^^^^
1540615628

llvm/include/llvm/IR/Intrinsics.td

+6
Original file line numberDiff line numberDiff line change
@@ -1019,9 +1019,15 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
10191019
// environment so they can be treated as readnone.
10201020
def int_sqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10211021
def int_powi : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>;
1022+
def int_asin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1023+
def int_acos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1024+
def int_atan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10221025
def int_sin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10231026
def int_cos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10241027
def int_tan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1028+
def int_sinh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1029+
def int_cosh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1030+
def int_tanh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10251031
def int_pow : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
10261032
[LLVMMatchType<0>, LLVMMatchType<0>]>;
10271033
def int_log : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;

llvm/lib/Target/DirectX/DXIL.td

+19
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,25 @@ def Sin : DXILOpMapping<13, unary, int_sin,
269269
def Tan : DXILOpMapping<14, unary, int_tan,
270270
"Returns tangent(theta) for theta in radians.",
271271
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
272+
def ACos : DXILOpMapping<15, unary, int_acos,
273+
"Returns the arccosine of each component of input.",
274+
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
275+
def ASin : DXILOpMapping<16, unary, int_asin,
276+
"Returns the arcsine of each component of input.",
277+
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
278+
def ATan : DXILOpMapping<17, unary, int_atan,
279+
"Returns the arctangent of each component of input.",
280+
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
281+
def HCos : DXILOpMapping<18, unary, int_cosh,
282+
"Returns the hyperbolic cosine of the specified value.",
283+
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
284+
def HSin : DXILOpMapping<19, unary, int_sinh,
285+
"Returns the hyperbolic sine of the specified value.",
286+
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
287+
def HTan : DXILOpMapping<20, unary, int_tanh,
288+
"Returns the hyperbolic tan of the specified value.",
289+
[llvm_halforfloat_ty, LLVMMatchType<0>]>;
290+
272291
def Exp2 : DXILOpMapping<21, unary, int_exp2,
273292
"Returns the base 2 exponential, or 2**x, of the specified value."
274293
"exp2(x) = 2**x.",

llvm/test/CodeGen/DirectX/acos.ll

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
2+
3+
; Make sure dxil operation function calls for acos are generated for float and half.
4+
5+
define noundef float @tan_float(float noundef %a) {
6+
entry:
7+
; CHECK:call float @dx.op.unary.f32(i32 15, float %{{.*}})
8+
%elt.acos = call float @llvm.acos.f32(float %a)
9+
ret float %elt.acos
10+
}
11+
12+
define noundef half @tan_half(half noundef %a) {
13+
entry:
14+
; CHECK:call half @dx.op.unary.f16(i32 15, half %{{.*}})
15+
%elt.acos = call half @llvm.acos.f16(half %a)
16+
ret half %elt.acos
17+
}
18+
19+
declare half @llvm.acos.f16(half)
20+
declare float @llvm.acos.f32(float)
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
2+
3+
; DXIL operation acos does not support double overload type
4+
; CHECK: LLVM ERROR: Invalid Overload
5+
6+
define noundef double @acos_double(double noundef %a) {
7+
entry:
8+
%1 = call double @llvm.acos.f64(double %a)
9+
ret double %1
10+
}

llvm/test/CodeGen/DirectX/asin.ll

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
2+
3+
; Make sure dxil operation function calls for asin are generated for float and half.
4+
5+
define noundef float @tan_float(float noundef %a) {
6+
entry:
7+
; CHECK:call float @dx.op.unary.f32(i32 16, float %{{.*}})
8+
%elt.asin = call float @llvm.asin.f32(float %a)
9+
ret float %elt.asin
10+
}
11+
12+
define noundef half @tan_half(half noundef %a) {
13+
entry:
14+
; CHECK:call half @dx.op.unary.f16(i32 16, half %{{.*}})
15+
%elt.asin = call half @llvm.asin.f16(half %a)
16+
ret half %elt.asin
17+
}
18+
19+
declare half @llvm.asin.f16(half)
20+
declare float @llvm.asin.f32(float)
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
2+
3+
; DXIL operation asin does not support double overload type
4+
; CHECK: LLVM ERROR: Invalid Overload
5+
6+
define noundef double @asin_double(double noundef %a) {
7+
entry:
8+
%1 = call double @llvm.asin.f64(double %a)
9+
ret double %1
10+
}

llvm/test/CodeGen/DirectX/atan.ll

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
2+
3+
; Make sure dxil operation function calls for atan are generated for float and half.
4+
5+
define noundef float @tan_float(float noundef %a) {
6+
entry:
7+
; CHECK:call float @dx.op.unary.f32(i32 17, float %{{.*}})
8+
%elt.atan = call float @llvm.atan.f32(float %a)
9+
ret float %elt.atan
10+
}
11+
12+
define noundef half @tan_half(half noundef %a) {
13+
entry:
14+
; CHECK:call half @dx.op.unary.f16(i32 17, half %{{.*}})
15+
%elt.atan = call half @llvm.atan.f16(half %a)
16+
ret half %elt.atan
17+
}
18+
19+
declare half @llvm.atan.f16(half)
20+
declare float @llvm.atan.f32(float)
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
2+
3+
; DXIL operation atan does not support double overload type
4+
; CHECK: LLVM ERROR: Invalid Overload
5+
6+
define noundef double @atan_double(double noundef %a) {
7+
entry:
8+
%1 = call double @llvm.atan.f64(double %a)
9+
ret double %1
10+
}

llvm/test/CodeGen/DirectX/cosh.ll

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
2+
3+
; Make sure dxil operation function calls for cosh are generated for float and half.
4+
5+
define noundef float @tan_float(float noundef %a) {
6+
entry:
7+
; CHECK:call float @dx.op.unary.f32(i32 18, float %{{.*}})
8+
%elt.cosh = call float @llvm.cosh.f32(float %a)
9+
ret float %elt.cosh
10+
}
11+
12+
define noundef half @tan_half(half noundef %a) {
13+
entry:
14+
; CHECK:call half @dx.op.unary.f16(i32 18, half %{{.*}})
15+
%elt.cosh = call half @llvm.cosh.f16(half %a)
16+
ret half %elt.cosh
17+
}
18+
19+
declare half @llvm.cosh.f16(half)
20+
declare float @llvm.cosh.f32(float)
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
2+
3+
; DXIL operation cosh does not support double overload type
4+
; CHECK: LLVM ERROR: Invalid Overload
5+
6+
define noundef double @cosh_double(double noundef %a) {
7+
entry:
8+
%1 = call double @llvm.cosh.f64(double %a)
9+
ret double %1
10+
}

0 commit comments

Comments
 (0)