Skip to content

Commit 3f3e208

Browse files
committed
[HLSL] Implementation of tan intrinsic
HLSL has a tan builtin defined here: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-tan Currently HLSL builtins redirect to clang builtins. However there is no tan clang builtin today. This change implements llvm#70082 Changes: 1. Create an llvm tan intrinsic. 2. Then expose that intrinsic to hlsl.
1 parent 6b33047 commit 3f3e208

File tree

13 files changed

+166
-1
lines changed

13 files changed

+166
-1
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in
665665
T __builtin_elementwise_exp2(T x) returns the base-2 exponential, 2^x, of the specified value floating point types
666666

667667
T __builtin_elementwise_sqrt(T x) return the square root of a floating-point number floating point types
668+
T __builtin_elementwise_tan(T x) return the tangent of x interpreted as an angle in radians floating point types
668669
T __builtin_elementwise_roundeven(T x) round x to the nearest integer value in floating point format, floating point types
669670
rounding halfway cases to even (that is, to the nearest value
670671
that is an even integer), regardless of the current rounding

clang/include/clang/Basic/Builtins.td

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

1287+
def ElementwiseTan : Builtin {
1288+
let Spellings = ["__builtin_elementwise_tan"];
1289+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1290+
let Prototype = "void(...)";
1291+
}
1292+
12871293
def ElementwiseTrunc : Builtin {
12881294
let Spellings = ["__builtin_elementwise_trunc"];
12891295
let Attributes = [NoThrow, Const, CustomTypeChecking];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3682,7 +3682,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
36823682
case Builtin::BI__builtin_elementwise_sin:
36833683
return RValue::get(
36843684
emitUnaryBuiltin(*this, E, llvm::Intrinsic::sin, "elt.sin"));
3685-
3685+
case Builtin::BI__builtin_elementwise_tan:
3686+
return RValue::get(
3687+
emitUnaryBuiltin(*this, E, llvm::Intrinsic::tan, "elt.tan"));
36863688
case Builtin::BI__builtin_elementwise_trunc:
36873689
return RValue::get(
36883690
emitUnaryBuiltin(*this, E, llvm::Intrinsic::trunc, "elt.trunc"));

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,38 @@ float sqrt(float In);
581581
_HLSL_BUILTIN_ALIAS(__builtin_sqrt)
582582
double sqrt(double In);
583583

584+
//===----------------------------------------------------------------------===//
585+
// tan builtins
586+
//===----------------------------------------------------------------------===//
587+
#ifdef __HLSL_ENABLE_16_BIT
588+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
589+
half tan(half);
590+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
591+
half2 tan(half2);
592+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
593+
half3 tan(half3);
594+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
595+
half4 tan(half4);
596+
#endif
597+
598+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
599+
float tan(float);
600+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
601+
float2 tan(float2);
602+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
603+
float3 tan(float3);
604+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
605+
float4 tan(float4);
606+
607+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
608+
double tan(double);
609+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
610+
double2 tan(double2);
611+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
612+
double3 tan(double3);
613+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_tan)
614+
double4 tan(double4);
615+
584616
//===----------------------------------------------------------------------===//
585617
// trunc builtins
586618
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaChecking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,6 +2782,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27822782
case Builtin::BI__builtin_elementwise_nearbyint:
27832783
case Builtin::BI__builtin_elementwise_sin:
27842784
case Builtin::BI__builtin_elementwise_sqrt:
2785+
case Builtin::BI__builtin_elementwise_tan:
27852786
case Builtin::BI__builtin_elementwise_trunc:
27862787
case Builtin::BI__builtin_elementwise_canonicalize: {
27872788
if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))

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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3+
// RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
4+
// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
5+
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
6+
// RUN: -D__HLSL_ENABLE_16_BIT -o - | FileCheck %s --check-prefix=NO_HALF
7+
8+
// CHECK: define noundef half @
9+
// CHECK: call half @llvm.tan.f16(
10+
// NO_HALF: define noundef float @"?test_tan_half@@YA$halff@$halff@@Z"(
11+
// NO_HALF: call float @llvm.tan.f32(
12+
half test_tan_half ( half p0 ) {
13+
return tan ( p0 );
14+
}
15+
// CHECK: define noundef <2 x half> @
16+
// CHECK: call <2 x half> @llvm.tan.v2f16
17+
// NO_HALF: define noundef <2 x float> @"?test_tan_float2@@YAT?$__vector@M$01@__clang@@T12@@Z"(
18+
// NO_HALF: call <2 x float> @llvm.tan.v2f32(
19+
half2 test_tan_half2 ( half2 p0 ) {
20+
return tan ( p0 );
21+
}
22+
// CHECK: define noundef <3 x half> @
23+
// CHECK: call <3 x half> @llvm.tan.v3f16
24+
// NO_HALF: define noundef <3 x float> @"?test_tan_float3@@YAT?$__vector@M$02@__clang@@T12@@Z"(
25+
// NO_HALF: call <3 x float> @llvm.tan.v3f32(
26+
half3 test_tan_half3 ( half3 p0 ) {
27+
return tan ( p0 );
28+
}
29+
// CHECK: define noundef <4 x half> @
30+
// CHECK: call <4 x half> @llvm.tan.v4f16
31+
// NO_HALF: define noundef <4 x float> @"?test_tan_float4@@YAT?$__vector@M$03@__clang@@T12@@Z"(
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: define noundef float @
38+
// CHECK: call float @llvm.tan.f32(
39+
float test_tan_float ( float p0 ) {
40+
return tan ( p0 );
41+
}
42+
// CHECK: define noundef <2 x float> @
43+
// CHECK: call <2 x float> @llvm.tan.v2f32
44+
float2 test_tan_float2 ( float2 p0 ) {
45+
return tan ( p0 );
46+
}
47+
// CHECK: define noundef <3 x float> @
48+
// CHECK: call <3 x float> @llvm.tan.v3f32
49+
float3 test_tan_float3 ( float3 p0 ) {
50+
return tan ( p0 );
51+
}
52+
// CHECK: define noundef <4 x float> @
53+
// CHECK: call <4 x float> @llvm.tan.v4f32
54+
float4 test_tan_float4 ( float4 p0 ) {
55+
return tan ( p0 );
56+
}

clang/test/Sema/aarch64-sve-vector-trig-ops.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ svfloat32_t test_cos_vv_i8mf8(svfloat32_t v) {
1616
return __builtin_elementwise_cos(v);
1717
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
1818
}
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
@@ -622,6 +622,27 @@ void test_builtin_elementwise_sqrt(int i, float f, double d, float4 v, int3 iv,
622622
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
623623
}
624624

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

627648
struct Foo s = __builtin_elementwise_trunc(f);

clang/test/Sema/riscv-rvv-vector-trig-ops.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,9 @@ vfloat32mf2_t test_cos_vv_i8mf8(vfloat32mf2_t v) {
1717
return __builtin_elementwise_cos(v);
1818
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
1919
}
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
@@ -118,6 +118,13 @@ void test_builtin_elementwise_sqrt() {
118118
static_assert(!is_const<decltype(__builtin_elementwise_sqrt(b))>::value);
119119
}
120120

121+
void test_builtin_elementwise_tan() {
122+
const float a = 42.0;
123+
float b = 42.3;
124+
static_assert(!is_const<decltype(__builtin_elementwise_tan(a))>::value);
125+
static_assert(!is_const<decltype(__builtin_elementwise_tan(b))>::value);
126+
}
127+
121128
void test_builtin_elementwise_log() {
122129
const float a = 42.0;
123130
float b = 42.3;

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,7 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
10101010
def int_powi : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>;
10111011
def int_sin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10121012
def int_cos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1013+
def int_tan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10131014
def int_pow : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
10141015
[LLVMMatchType<0>, LLVMMatchType<0>]>;
10151016
def int_log : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;

0 commit comments

Comments
 (0)