Skip to content

Commit 4b4ea6d

Browse files
[HLSL] Make casting functions constexpr (#108902)
This marks the `bit_cast` helper as `constexpr` and allows the casts implemented with it to also be `constexpr`. This is largely not a functional change, but it enables using the casts in expressions that need to be resolved at compile time as demonstrated with the static asserts in the new tests. --------- Co-authored-by: joaosaffran <[email protected]>
1 parent 4d62102 commit 4b4ea6d

File tree

5 files changed

+35
-16
lines changed

5 files changed

+35
-16
lines changed

clang/lib/Headers/hlsl/hlsl_detail.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,23 @@ namespace hlsl {
1313

1414
namespace __detail {
1515

16-
#define _HLSL_INLINE \
17-
__attribute__((__always_inline__, __nodebug__)) static inline
18-
1916
template <bool B, typename T> struct enable_if {};
2017

2118
template <typename T> struct enable_if<true, T> {
2219
using Type = T;
2320
};
2421

22+
template <bool B, class T = void>
23+
using enable_if_t = typename enable_if<B, T>::Type;
24+
2525
template <typename U, typename T, int N>
26-
_HLSL_INLINE typename enable_if<sizeof(U) == sizeof(T), vector<U, N> >::Type
26+
constexpr enable_if_t<sizeof(U) == sizeof(T), vector<U, N>>
2727
bit_cast(vector<T, N> V) {
2828
return __builtin_bit_cast(vector<U, N>, V);
2929
}
3030

3131
template <typename U, typename T>
32-
_HLSL_INLINE typename enable_if<sizeof(U) == sizeof(T), U>::Type bit_cast(T F) {
32+
constexpr enable_if_t<sizeof(U) == sizeof(T), U> bit_cast(T F) {
3333
return __builtin_bit_cast(U, F);
3434
}
3535

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,11 @@ bool any(double4);
370370
/// \param Val The input value.
371371

372372
template <typename T, int N>
373-
_HLSL_INLINE vector<float, N> asfloat(vector<T, N> V) {
373+
constexpr vector<float, N> asfloat(vector<T, N> V) {
374374
return __detail::bit_cast<float, T, N>(V);
375375
}
376376

377-
template <typename T> _HLSL_INLINE float asfloat(T F) {
377+
template <typename T> constexpr float asfloat(T F) {
378378
return __detail::bit_cast<float, T>(F);
379379
}
380380

@@ -414,12 +414,11 @@ float4 asin(float4);
414414
/// \brief Interprets the bit pattern of x as an unsigned integer.
415415
/// \param Val The input value.
416416

417-
template <typename T, int N>
418-
_HLSL_INLINE vector<uint, N> asuint(vector<T, N> V) {
417+
template <typename T, int N> constexpr vector<uint, N> asuint(vector<T, N> V) {
419418
return __detail::bit_cast<uint, T, N>(V);
420419
}
421420

422-
template <typename T> _HLSL_INLINE uint asuint(T F) {
421+
template <typename T> constexpr uint asuint(T F) {
423422
return __detail::bit_cast<uint, T>(F);
424423
}
425424

clang/test/CodeGenHLSL/builtins/asuint.hlsl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -O1 -o - | FileCheck %s
22

3-
// CHECK: define {{.*}}test_uint{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
3+
// CHECK: define {{.*}}test_uint{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
44
// CHECK-NOT: bitcast
55
// CHECK: ret i32 [[VAL]]
66
uint test_uint(uint p0) {
77
return asuint(p0);
88
}
99

10-
// CHECK: define {{.*}}test_int{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
10+
// CHECK: define {{.*}}test_int{{.*}}(i32 {{.*}} [[VAL:%.*]]){{.*}}
1111
// CHECK-NOT: bitcast
1212
// CHECK: ret i32 [[VAL]]
1313
uint test_int(int p0) {
1414
return asuint(p0);
1515
}
1616

17-
// CHECK: define {{.*}}test_float{{.*}}(float {{.*}} [[VAL:%.*]]){{.*}}
17+
// CHECK: define {{.*}}test_float{{.*}}(float {{.*}} [[VAL:%.*]]){{.*}}
1818
// CHECK: bitcast float [[VAL]] to i32
1919
uint test_float(float p0) {
2020
return asuint(p0);
2121
}
2222

23-
// CHECK: define {{.*}}test_vector_uint{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
23+
// CHECK: define {{.*}}test_vector_uint{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
2424
// CHECK-NOT: bitcast
2525
// CHECK: ret <4 x i32> [[VAL]]
2626
uint4 test_vector_uint(uint4 p0) {
2727
return asuint(p0);
2828
}
2929

30-
// CHECK: define {{.*}}test_vector_int{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
30+
// CHECK: define {{.*}}test_vector_int{{.*}}(<4 x i32> {{.*}} [[VAL:%.*]]){{.*}}
3131
// CHECK-NOT: bitcast
3232
// CHECK: ret <4 x i32> [[VAL]]
3333
uint4 test_vector_int(int4 p0) {
3434
return asuint(p0);
3535
}
3636

37-
// CHECK: define {{.*}}test_vector_float{{.*}}(<4 x float> {{.*}} [[VAL:%.*]]){{.*}}
37+
// CHECK: define {{.*}}test_vector_float{{.*}}(<4 x float> {{.*}} [[VAL:%.*]]){{.*}}
3838
// CHECK: bitcast <4 x float> [[VAL]] to <4 x i32>
3939
uint4 test_vector_float(float4 p0) {
4040
return asuint(p0);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify
2+
3+
// expected-no-diagnostics
4+
5+
// Because asfloat should be constant evaluated, all the static asserts below
6+
// should work!
7+
void ConstExprTest() {
8+
static_assert(asfloat(0x3f800000) == 1.0f, "One");
9+
static_assert(asfloat(0x40000000.xxx).y == 2.0f, "Two");
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify
2+
3+
// expected-no-diagnostics
4+
5+
// Because asuint should be constant evaluated, all the static asserts below
6+
// should work!
7+
void ConstExprTest() {
8+
static_assert(asuint(1) == 1u, "One");
9+
static_assert(asuint(2.xxx).y == 2u, "Two");
10+
}

0 commit comments

Comments
 (0)