Skip to content

Commit 31b45a9

Browse files
authored
[clang][hlsl] Add tan intrinsic part 1 (#90276)
This change is an implementation of #87367's investigation on supporting IEEE math operations as intrinsics. Which was discussed in this RFC: https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294 If you want an overarching view of how this will all connect see: #90088 Changes: - `clang/docs/LanguageExtensions.rst` - Document the new elementwise tan builtin. - `clang/include/clang/Basic/Builtins.td` - Implement the tan builtin. - `clang/lib/CodeGen/CGBuiltin.cpp` - invoke the tan intrinsic on uses of the builtin - `clang/lib/Headers/hlsl/hlsl_intrinsics.h` - Associate the tan builtin with the equivalent hlsl apis - `clang/lib/Sema/SemaChecking.cpp` - Add generic sema checks as well as HLSL specifc sema checks to the tan builtin - `llvm/include/llvm/IR/Intrinsics.td` - Create the tan intrinsic - `llvm/docs/LangRef.rst` - Document the tan intrinsic
1 parent 1c8c2fd commit 31b45a9

15 files changed

+236
-38
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in
656656
T __builtin_elementwise_ceil(T x) return the smallest integral value greater than or equal to x floating point types
657657
T __builtin_elementwise_sin(T x) return the sine of x interpreted as an angle in radians floating point types
658658
T __builtin_elementwise_cos(T x) return the cosine of x interpreted as an angle in radians floating point types
659+
T __builtin_elementwise_tan(T x) return the tangent of x interpreted as an angle in radians floating point types
659660
T __builtin_elementwise_floor(T x) return the largest integral value less than or equal to x floating point types
660661
T __builtin_elementwise_log(T x) return the natural logarithm of x floating point types
661662
T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,12 @@ def ElementwiseSqrt : Builtin {
13261326
let Prototype = "void(...)";
13271327
}
13281328

1329+
def ElementwiseTan : Builtin {
1330+
let Spellings = ["__builtin_elementwise_tan"];
1331+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1332+
let Prototype = "void(...)";
1333+
}
1334+
13291335
def ElementwiseTrunc : Builtin {
13301336
let Spellings = ["__builtin_elementwise_trunc"];
13311337
let Attributes = [NoThrow, Const, CustomTypeChecking];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3822,7 +3822,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
38223822
case Builtin::BI__builtin_elementwise_sin:
38233823
return RValue::get(
38243824
emitUnaryBuiltin(*this, E, llvm::Intrinsic::sin, "elt.sin"));
3825-
3825+
case Builtin::BI__builtin_elementwise_tan:
3826+
return RValue::get(
3827+
emitUnaryBuiltin(*this, E, llvm::Intrinsic::tan, "elt.tan"));
38263828
case Builtin::BI__builtin_elementwise_trunc:
38273829
return RValue::get(
38283830
emitUnaryBuiltin(*this, E, llvm::Intrinsic::trunc, "elt.trunc"));

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,29 @@ float3 sqrt(float3);
14411441
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt)
14421442
float4 sqrt(float4);
14431443

1444+
//===----------------------------------------------------------------------===//
1445+
// tan builtins
1446+
//===----------------------------------------------------------------------===//
1447+
#ifdef __HLSL_ENABLE_16_BIT
1448+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1449+
half tan(half);
1450+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1451+
half2 tan(half2);
1452+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1453+
half3 tan(half3);
1454+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1455+
half4 tan(half4);
1456+
#endif
1457+
1458+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1459+
float tan(float);
1460+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1461+
float2 tan(float2);
1462+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1463+
float3 tan(float3);
1464+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
1465+
float4 tan(float4);
1466+
14441467
//===----------------------------------------------------------------------===//
14451468
// trunc builtins
14461469
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3047,6 +3047,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
30473047
case Builtin::BI__builtin_elementwise_nearbyint:
30483048
case Builtin::BI__builtin_elementwise_sin:
30493049
case Builtin::BI__builtin_elementwise_sqrt:
3050+
case Builtin::BI__builtin_elementwise_tan:
30503051
case Builtin::BI__builtin_elementwise_trunc:
30513052
case Builtin::BI__builtin_elementwise_canonicalize: {
30523053
if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
@@ -5677,6 +5678,7 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
56775678
case Builtin::BI__builtin_elementwise_roundeven:
56785679
case Builtin::BI__builtin_elementwise_sin:
56795680
case Builtin::BI__builtin_elementwise_sqrt:
5681+
case Builtin::BI__builtin_elementwise_tan:
56805682
case Builtin::BI__builtin_elementwise_trunc: {
56815683
if (CheckFloatOrHalfRepresentations(this, TheCall))
56825684
return true;

clang/test/CodeGen/builtins-elementwise-math.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,22 @@ void test_builtin_elementwise_sqrt(float f1, float f2, double d1, double d2,
604604
vf2 = __builtin_elementwise_sqrt(vf1);
605605
}
606606

607+
void test_builtin_elementwise_tan(float f1, float f2, double d1, double d2,
608+
float4 vf1, float4 vf2) {
609+
// CHECK-LABEL: define void @test_builtin_elementwise_tan(
610+
// CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4
611+
// CHECK-NEXT: call float @llvm.tan.f32(float [[F1]])
612+
f2 = __builtin_elementwise_tan(f1);
613+
614+
// CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8
615+
// CHECK-NEXT: call double @llvm.tan.f64(double [[D1]])
616+
d2 = __builtin_elementwise_tan(d1);
617+
618+
// CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16
619+
// CHECK-NEXT: call <4 x float> @llvm.tan.v4f32(<4 x float> [[VF1]])
620+
vf2 = __builtin_elementwise_tan(vf1);
621+
}
622+
607623
void test_builtin_elementwise_trunc(float f1, float f2, double d1, double d2,
608624
float4 vf1, float4 vf2) {
609625
// CHECK-LABEL: define void @test_builtin_elementwise_trunc(

clang/test/CodeGen/strictfp-elementwise-bulitins.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,16 @@ float4 strict_elementwise_sqrt(float4 a) {
187187
return __builtin_elementwise_sqrt(a);
188188
}
189189

190+
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z22strict_elementwise_tanDv4_f
191+
// CHECK-SAME: (<4 x float> noundef [[A:%.*]]) local_unnamed_addr #[[ATTR2]] {
192+
// CHECK-NEXT: entry:
193+
// CHECK-NEXT: [[ELT_TAN:%.*]] = tail call <4 x float> @llvm.tan.v4f32(<4 x float> [[A]]) #[[ATTR4]]
194+
// CHECK-NEXT: ret <4 x float> [[ELT_TAN]]
195+
//
196+
float4 strict_elementwise_tan(float4 a) {
197+
return __builtin_elementwise_tan(a);
198+
}
199+
190200
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z24strict_elementwise_truncDv4_f
191201
// CHECK-SAME: (<4 x float> noundef [[A:%.*]]) local_unnamed_addr #[[ATTR2]] {
192202
// CHECK-NEXT: entry:
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
4+
// RUN: --check-prefixes=CHECK,NATIVE_HALF
5+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
6+
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
7+
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
8+
9+
// CHECK-LABEL: test_tan_half
10+
// NATIVE_HALF: call half @llvm.tan.f16
11+
// NO_HALF: call float @llvm.tan.f32
12+
half test_tan_half ( half p0 ) {
13+
return tan ( p0 );
14+
}
15+
16+
// CHECK-LABEL: test_tan_half2
17+
// NATIVE_HALF: call <2 x half> @llvm.tan.v2f16
18+
// NO_HALF: call <2 x float> @llvm.tan.v2f32
19+
half2 test_tan_half2 ( half2 p0 ) {
20+
return tan ( p0 );
21+
}
22+
23+
// CHECK-LABEL: test_tan_half3
24+
// NATIVE_HALF: call <3 x half> @llvm.tan.v3f16
25+
// NO_HALF: call <3 x float> @llvm.tan.v3f32
26+
half3 test_tan_half3 ( half3 p0 ) {
27+
return tan ( p0 );
28+
}
29+
30+
// CHECK-LABEL: test_tan_half4
31+
// NATIVE_HALF: call <4 x half> @llvm.tan.v4f16
32+
// NO_HALF: call <4 x float> @llvm.tan.v4f32
33+
half4 test_tan_half4 ( half4 p0 ) {
34+
return tan ( p0 );
35+
}
36+
37+
// CHECK-LABEL: test_tan_float
38+
// CHECK: call float @llvm.tan.f32
39+
float test_tan_float ( float p0 ) {
40+
return tan ( p0 );
41+
}
42+
43+
// CHECK-LABEL: test_tan_float2
44+
// CHECK: call <2 x float> @llvm.tan.v2f32
45+
float2 test_tan_float2 ( float2 p0 ) {
46+
return tan ( p0 );
47+
}
48+
49+
// CHECK-LABEL: test_tan_float3
50+
// CHECK: call <3 x float> @llvm.tan.v3f32
51+
float3 test_tan_float3 ( float3 p0 ) {
52+
return tan ( p0 );
53+
}
54+
55+
// CHECK-LABEL: test_tan_float4
56+
// CHECK: call <4 x float> @llvm.tan.v4f32
57+
float4 test_tan_float4 ( float4 p0 ) {
58+
return tan ( p0 );
59+
}
Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
1-
// RUN: %clang_cc1 -triple aarch64 -target-feature +sve \
2-
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
3-
// REQUIRES: aarch64-registered-target
4-
5-
#include <arm_sve.h>
6-
7-
8-
svfloat32_t test_sin_vv_i8mf8(svfloat32_t v) {
9-
10-
return __builtin_elementwise_sin(v);
11-
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
12-
}
13-
14-
svfloat32_t test_cos_vv_i8mf8(svfloat32_t v) {
15-
16-
return __builtin_elementwise_cos(v);
17-
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
18-
}
1+
// RUN: %clang_cc1 -triple aarch64 -target-feature +sve \
2+
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
3+
// REQUIRES: aarch64-registered-target
4+
5+
#include <arm_sve.h>
6+
7+
8+
svfloat32_t test_sin_vv_i8mf8(svfloat32_t v) {
9+
10+
return __builtin_elementwise_sin(v);
11+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
12+
}
13+
14+
svfloat32_t test_cos_vv_i8mf8(svfloat32_t v) {
15+
16+
return __builtin_elementwise_cos(v);
17+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
18+
}
19+
20+
svfloat32_t test_tan_vv_i8mf8(svfloat32_t v) {
21+
22+
return __builtin_elementwise_tan(v);
23+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
24+
}

clang/test/Sema/builtins-elementwise-math.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,27 @@ void test_builtin_elementwise_sqrt(int i, float f, double d, float4 v, int3 iv,
626626
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
627627
}
628628

629+
void test_builtin_elementwise_tan(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
630+
631+
struct Foo s = __builtin_elementwise_tan(f);
632+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'float'}}
633+
634+
i = __builtin_elementwise_tan();
635+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
636+
637+
i = __builtin_elementwise_tan(i);
638+
// expected-error@-1 {{1st argument must be a floating point type (was 'int')}}
639+
640+
i = __builtin_elementwise_tan(f, f);
641+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
642+
643+
u = __builtin_elementwise_tan(u);
644+
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned int')}}
645+
646+
uv = __builtin_elementwise_tan(uv);
647+
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
648+
}
649+
629650
void test_builtin_elementwise_trunc(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
630651

631652
struct Foo s = __builtin_elementwise_trunc(f);
Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1-
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \
2-
// RUN: -target-feature +v -target-feature +zfh -target-feature +zvfh \
3-
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
4-
// REQUIRES: riscv-registered-target
5-
6-
#include <riscv_vector.h>
7-
8-
9-
vfloat32mf2_t test_sin_vv_i8mf8(vfloat32mf2_t v) {
10-
11-
return __builtin_elementwise_sin(v);
12-
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
13-
}
14-
15-
vfloat32mf2_t test_cos_vv_i8mf8(vfloat32mf2_t v) {
16-
17-
return __builtin_elementwise_cos(v);
18-
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
19-
}
1+
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \
2+
// RUN: -target-feature +v -target-feature +zfh -target-feature +zvfh \
3+
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
4+
// REQUIRES: riscv-registered-target
5+
6+
#include <riscv_vector.h>
7+
8+
9+
vfloat32mf2_t test_sin_vv_i8mf8(vfloat32mf2_t v) {
10+
11+
return __builtin_elementwise_sin(v);
12+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
13+
}
14+
15+
vfloat32mf2_t test_cos_vv_i8mf8(vfloat32mf2_t v) {
16+
17+
return __builtin_elementwise_cos(v);
18+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
19+
}
20+
21+
vfloat32mf2_t test_tan_vv_i8mf8(vfloat32mf2_t v) {
22+
23+
return __builtin_elementwise_tan(v);
24+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
25+
}

clang/test/SemaCXX/builtins-elementwise-math.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ void test_builtin_elementwise_sin() {
111111
static_assert(!is_const<decltype(__builtin_elementwise_sin(b))>::value);
112112
}
113113

114+
void test_builtin_elementwise_tan() {
115+
const float a = 42.0;
116+
float b = 42.3;
117+
static_assert(!is_const<decltype(__builtin_elementwise_tan(a))>::value);
118+
static_assert(!is_const<decltype(__builtin_elementwise_tan(b))>::value);
119+
}
120+
114121
void test_builtin_elementwise_sqrt() {
115122
const float a = 42.0;
116123
float b = 42.3;

clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin
1010
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt
1111
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_roundeven
12+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_tan
1213
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc
1314

1415
double2 test_double_builtin(double2 p0) {

llvm/docs/LangRef.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15272,6 +15272,43 @@ trapping or setting ``errno``.
1527215272
When specified with the fast-math-flag 'afn', the result may be approximated
1527315273
using a less accurate calculation.
1527415274

15275+
'``llvm.tan.*``' Intrinsic
15276+
^^^^^^^^^^^^^^^^^^^^^^^^^^
15277+
15278+
Syntax:
15279+
"""""""
15280+
15281+
This is an overloaded intrinsic. You can use ``llvm.tan`` on any
15282+
floating-point or vector of floating-point type. Not all targets support
15283+
all types however.
15284+
15285+
::
15286+
15287+
declare float @llvm.tan.f32(float %Val)
15288+
declare double @llvm.tan.f64(double %Val)
15289+
declare x86_fp80 @llvm.tan.f80(x86_fp80 %Val)
15290+
declare fp128 @llvm.tan.f128(fp128 %Val)
15291+
declare ppc_fp128 @llvm.tan.ppcf128(ppc_fp128 %Val)
15292+
15293+
Overview:
15294+
"""""""""
15295+
15296+
The '``llvm.tan.*``' intrinsics return the tangent of the operand.
15297+
15298+
Arguments:
15299+
""""""""""
15300+
15301+
The argument and return value are floating-point numbers of the same type.
15302+
15303+
Semantics:
15304+
""""""""""
15305+
15306+
Return the same value as a corresponding libm '``tan``' function but without
15307+
trapping or setting ``errno``.
15308+
15309+
When specified with the fast-math-flag 'afn', the result may be approximated
15310+
using a less accurate calculation.
15311+
1527515312
'``llvm.pow.*``' Intrinsic
1527615313
^^^^^^^^^^^^^^^^^^^^^^^^^^
1527715314

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,7 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
10251025
def int_powi : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>;
10261026
def int_sin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10271027
def int_cos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1028+
def int_tan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10281029
def int_pow : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
10291030
[LLVMMatchType<0>, LLVMMatchType<0>]>;
10301031
def int_log : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;

0 commit comments

Comments
 (0)