Skip to content

Commit 8664e3d

Browse files
committed
[HLSL][clang] Add elementwise builtin for atan2 (p3)
This change is part of this proposal: https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294 - Add HLSL frontend for atan2 - Add clang Builtin, map to new llvm.atan2 - SemaChecking restrict to floating point and 2 args - SemaHLSL restrict to float or half. - Add to clang ReleaseNotes.rst and LanguageExtensions.rst
1 parent 1eecc13 commit 8664e3d

15 files changed

+183
-0
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in
660660
T __builtin_elementwise_asin(T x) return the arcsine of x interpreted as an angle in radians floating point types
661661
T __builtin_elementwise_acos(T x) return the arccosine of x interpreted as an angle in radians floating point types
662662
T __builtin_elementwise_atan(T x) return the arctangent of x interpreted as an angle in radians floating point types
663+
T __builtin_elementwise_atan2(T y, T x) return the arctangent of y/x floating point types
663664
T __builtin_elementwise_sinh(T x) return the hyperbolic sine of angle x in radians floating point types
664665
T __builtin_elementwise_cosh(T x) return the hyperbolic cosine of angle x in radians floating point types
665666
T __builtin_elementwise_tanh(T x) return the hyperbolic tangent of angle x in radians floating point types

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,8 @@ DWARF Support in Clang
536536
Floating Point Support in Clang
537537
-------------------------------
538538

539+
- Add ``__builtin_elementwise_atan2`` builtin for floating point types only.
540+
539541
Fixed Point Support in Clang
540542
----------------------------
541543

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,12 @@ def ElementwiseATan : Builtin {
12501250
let Prototype = "void(...)";
12511251
}
12521252

1253+
def ElementwiseATan2 : Builtin {
1254+
let Spellings = ["__builtin_elementwise_atan2"];
1255+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1256+
let Prototype = "void(...)";
1257+
}
1258+
12531259
def ElementwiseBitreverse : Builtin {
12541260
let Spellings = ["__builtin_elementwise_bitreverse"];
12551261
let Attributes = [NoThrow, Const, CustomTypeChecking];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3835,6 +3835,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
38353835
case Builtin::BI__builtin_elementwise_atan:
38363836
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
38373837
*this, E, llvm::Intrinsic::atan, "elt.atan"));
3838+
case Builtin::BI__builtin_elementwise_atan2:
3839+
return RValue::get(emitBuiltinWithOneOverloadedType<2>(
3840+
*this, E, llvm::Intrinsic::atan2, "elt.atan2"));
38383841
case Builtin::BI__builtin_elementwise_ceil:
38393842
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
38403843
*this, E, llvm::Intrinsic::ceil, "elt.ceil"));

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,36 @@ float3 atan(float3);
450450
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan)
451451
float4 atan(float4);
452452

453+
//===----------------------------------------------------------------------===//
454+
// atan2 builtins
455+
//===----------------------------------------------------------------------===//
456+
457+
/// \fn T atan2(T y, T x)
458+
/// \brief Returns the arctangent of y/x, using the signs of the arguments to
459+
/// determine the correct quadrant.
460+
/// \param y The y-coordinate.
461+
/// \param x The x-coordinate.
462+
463+
#ifdef __HLSL_ENABLE_16_BIT
464+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
465+
half atan2(half y, half x);
466+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
467+
half2 atan2(half2 y, half2 x);
468+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
469+
half3 atan2(half3 y, half3 x);
470+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
471+
half4 atan2(half4 y, half4 x);
472+
#endif
473+
474+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
475+
float atan2(float y, float x);
476+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
477+
float2 atan2(float2 y, float2 x);
478+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
479+
float3 atan2(float3 y, float3 x);
480+
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_atan2)
481+
float4 atan2(float4 y, float4 x);
482+
453483
//===----------------------------------------------------------------------===//
454484
// ceil builtins
455485
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaChecking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27552755

27562756
// These builtins restrict the element type to floating point
27572757
// types only, and take in two arguments.
2758+
case Builtin::BI__builtin_elementwise_atan2:
27582759
case Builtin::BI__builtin_elementwise_pow: {
27592760
if (BuiltinElementwiseMath(TheCall))
27602761
return ExprError();

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
17711771
case Builtin::BI__builtin_elementwise_acos:
17721772
case Builtin::BI__builtin_elementwise_asin:
17731773
case Builtin::BI__builtin_elementwise_atan:
1774+
case Builtin::BI__builtin_elementwise_atan2:
17741775
case Builtin::BI__builtin_elementwise_ceil:
17751776
case Builtin::BI__builtin_elementwise_cos:
17761777
case Builtin::BI__builtin_elementwise_cosh:

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,26 @@ void test_builtin_elementwise_atan(float f1, float f2, double d1, double d2,
441441
vf2 = __builtin_elementwise_atan(vf1);
442442
}
443443

444+
void test_builtin_elementwise_atan2(float f1, float f2, float f3, double d1,
445+
double d2, double d3, float4 vf1,
446+
float4 vf2, float4 vf3) {
447+
// CHECK-LABEL: define void @test_builtin_elementwise_atan2(
448+
// CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4
449+
// CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4
450+
// CHECK-NEXT: call float @llvm.atan2.f32(float [[F1]], float [[F2]])
451+
f3 = __builtin_elementwise_atan2(f1, f2);
452+
453+
// CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8
454+
// CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8
455+
// CHECK-NEXT: call double @llvm.atan2.f64(double [[D1]], double [[D2]])
456+
d3 = __builtin_elementwise_atan2(d1, d2);
457+
458+
// CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16
459+
// CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
460+
// CHECK-NEXT: call <4 x float> @llvm.atan2.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
461+
vf3 = __builtin_elementwise_atan2(vf1, vf2);
462+
}
463+
444464
void test_builtin_elementwise_cos(float f1, float f2, double d1, double d2,
445465
float4 vf1, float4 vf2) {
446466
// CHECK-LABEL: define void @test_builtin_elementwise_cos(

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,16 @@ float4 strict_elementwise_tanh(float4 a) {
257257
return __builtin_elementwise_tanh(a);
258258
}
259259

260+
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z24strict_elementwise_atan2Dv4_fS_
261+
// CHECK-SAME: (<4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) local_unnamed_addr #[[ATTR2]] {
262+
// CHECK-NEXT: entry:
263+
// CHECK-NEXT: [[ELT_ATAN2:%.*]] = tail call <4 x float> @llvm.atan2.v4f32(<4 x float> [[A]], <4 x float> [[B]]) #[[ATTR4]]
264+
// CHECK-NEXT: ret <4 x float> [[ELT_ATAN2]]
265+
//
266+
float4 strict_elementwise_atan2(float4 a, float4 b) {
267+
return __builtin_elementwise_atan2(a, b);
268+
}
269+
260270
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z24strict_elementwise_truncDv4_f
261271
// CHECK-SAME: (<4 x float> noundef [[A:%.*]]) local_unnamed_addr #[[ATTR2]] {
262272
// 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_atan2_half
10+
// NATIVE_HALF: call half @llvm.atan2.f16
11+
// NO_HALF: call float @llvm.atan2.f32
12+
half test_atan2_half (half p0, half p1) {
13+
return atan2(p0, p1);
14+
}
15+
16+
// CHECK-LABEL: test_atan2_half2
17+
// NATIVE_HALF: call <2 x half> @llvm.atan2.v2f16
18+
// NO_HALF: call <2 x float> @llvm.atan2.v2f32
19+
half2 test_atan2_half2 (half2 p0, half2 p1) {
20+
return atan2(p0, p1);
21+
}
22+
23+
// CHECK-LABEL: test_atan2_half3
24+
// NATIVE_HALF: call <3 x half> @llvm.atan2.v3f16
25+
// NO_HALF: call <3 x float> @llvm.atan2.v3f32
26+
half3 test_atan2_half3 (half3 p0, half3 p1) {
27+
return atan2(p0, p1);
28+
}
29+
30+
// CHECK-LABEL: test_atan2_half4
31+
// NATIVE_HALF: call <4 x half> @llvm.atan2.v4f16
32+
// NO_HALF: call <4 x float> @llvm.atan2.v4f32
33+
half4 test_atan2_half4 (half4 p0, half4 p1) {
34+
return atan2(p0, p1);
35+
}
36+
37+
// CHECK-LABEL: test_atan2_float
38+
// CHECK: call float @llvm.atan2.f32
39+
float test_atan2_float (float p0, float p1) {
40+
return atan2(p0, p1);
41+
}
42+
43+
// CHECK-LABEL: test_atan2_float2
44+
// CHECK: call <2 x float> @llvm.atan2.v2f32
45+
float2 test_atan2_float2 (float2 p0, float2 p1) {
46+
return atan2(p0, p1);
47+
}
48+
49+
// CHECK-LABEL: test_atan2_float3
50+
// CHECK: call <3 x float> @llvm.atan2.v3f32
51+
float3 test_atan2_float3 (float3 p0, float3 p1) {
52+
return atan2(p0, p1);
53+
}
54+
55+
// CHECK-LABEL: test_atan2_float4
56+
// CHECK: call <4 x float> @llvm.atan2.v4f32
57+
float4 test_atan2_float4 (float4 p0, float4 p1) {
58+
return atan2(p0, p1);
59+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ svfloat32_t test_atan_vv_i8mf8(svfloat32_t v) {
2222
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
2323
}
2424

25+
svfloat32_t test_atan2_vv_i8mf8(svfloat32_t v) {
26+
27+
return __builtin_elementwise_atan2(v, v);
28+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
29+
}
30+
2531
svfloat32_t test_sin_vv_i8mf8(svfloat32_t v) {
2632

2733
return __builtin_elementwise_sin(v);

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,30 @@ void test_builtin_elementwise_atan(int i, float f, double d, float4 v, int3 iv,
764764
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
765765
}
766766

767+
void test_builtin_elementwise_atan2(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
768+
769+
struct Foo s = __builtin_elementwise_atan2(f, f);
770+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'float'}}
771+
772+
i = __builtin_elementwise_atan2();
773+
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
774+
775+
i = __builtin_elementwise_atan2(f);
776+
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
777+
778+
i = __builtin_elementwise_atan2(i, i);
779+
// expected-error@-1 {{1st argument must be a floating point type (was 'int')}}
780+
781+
i = __builtin_elementwise_atan2(f, f, f);
782+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
783+
784+
u = __builtin_elementwise_atan2(u, u);
785+
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned int')}}
786+
787+
uv = __builtin_elementwise_atan2(uv, uv);
788+
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
789+
}
790+
767791
void test_builtin_elementwise_tan(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
768792

769793
struct Foo s = __builtin_elementwise_tan(f);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ vfloat32mf2_t test_asin_vv_i8mf8(vfloat32mf2_t v) {
2323
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
2424
}
2525

26+
vfloat32mf2_t test_atan2_vv_i8mf8(vfloat32mf2_t v) {
27+
28+
return __builtin_elementwise_atan2(v, v);
29+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
30+
}
31+
2632
vfloat32mf2_t test_sin_vv_i8mf8(vfloat32mf2_t v) {
2733

2834
return __builtin_elementwise_sin(v);

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ void test_builtin_elementwise_atan() {
146146
static_assert(!is_const<decltype(__builtin_elementwise_atan(b))>::value);
147147
}
148148

149+
void test_builtin_elementwise_atan2() {
150+
const float a = 42.0;
151+
float b = 42.3;
152+
static_assert(!is_const<decltype(__builtin_elementwise_atan2(a, a))>::value);
153+
static_assert(!is_const<decltype(__builtin_elementwise_atan2(b, b))>::value);
154+
}
155+
149156
void test_builtin_elementwise_tan() {
150157
const float a = 42.0;
151158
float b = 42.3;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// 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_atan2
2+
// 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_pow
3+
4+
double2 test_double_builtin(double2 p0, double2 p1) {
5+
return TEST_FUNC(p0, p1);
6+
// expected-error@-1 {{passing 'double2' (aka 'vector<double, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
7+
}

0 commit comments

Comments
 (0)